Esempio n. 1
0
 /// <summary>
 /// Sync only.
 /// </summary>
 public void Destroy()
 {
     if (FCO != null && IsAdded)
     {
         OwningRegion.RemoveChunkQuiet(FCO);
         IsAdded = false;
     }
     if (_VBO != null)
     {
         VBO tV = _VBO;
         lock (OwningRegion.TheClient.vbos)
         {
             if (tV.generated && OwningRegion.TheClient.vbos.Count < 120)
             {
                 OwningRegion.TheClient.vbos.Push(tV);
             }
             else
             {
                 tV.Destroy();
             }
         }
         _VBO = null;
     }
     DestroyPlants();
 }
Esempio n. 2
0
 public override void DestroyBody()
 {
     if (vbo != null)
     {
         vbo.Destroy();
     }
     base.DestroyBody();
 }
 public override void Recalculate()
 {
     Position = ((Maxes - Mins) / 2) + Mins;
     PrimaryEditor.ContextView.Control.MakeCurrent();
     if (MyVBO != null)
     {
         MyVBO.Destroy();
     }
     MyVBO = new VBO();
     MyVBO.Prepare();
     MyVBO.Tex = PrimaryEditor.ContextView.Textures.GetTexture(Texture);
     MyVBO.AddSide(new Location(0, 0, 1), Coords[0]);
     MyVBO.AddSide(new Location(0, 0, -1), Coords[1]);
     MyVBO.AddSide(new Location(1, 0, 0), Coords[2]);
     MyVBO.AddSide(new Location(-1, 0, 0), Coords[3]);
     MyVBO.AddSide(new Location(0, 1, 0), Coords[4]);
     MyVBO.AddSide(new Location(0, -1, 0), Coords[5]);
     MyVBO.GenerateVBO();
 }
Esempio n. 4
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);
            }
        }
Esempio n. 5
0
        // TODO: Make asyncable!
        public void SetupVBO()
        {
            List <OpenTK.Vector3> Vertices  = new List <OpenTK.Vector3>(XWidth * YWidth * ZWidth);
            List <OpenTK.Vector3> Normals   = new List <OpenTK.Vector3>(XWidth * YWidth * ZWidth);
            List <OpenTK.Vector3> TexCoords = new List <OpenTK.Vector3>(XWidth * YWidth * ZWidth);
            List <OpenTK.Vector4> Colrs     = new List <OpenTK.Vector4>(XWidth * YWidth * ZWidth);
            List <OpenTK.Vector4> TCOLs     = new List <OpenTK.Vector4>(XWidth * YWidth * ZWidth);
            List <OpenTK.Vector3> Tangs     = new List <OpenTK.Vector3>(XWidth * YWidth * ZWidth);

            for (int x = 0; x < XWidth; x++)
            {
                for (int y = 0; y < YWidth; y++)
                {
                    for (int z = 0; z < ZWidth; z++)
                    {
                        BlockInternal c = GetBlockAt(x, y, z);
                        if (((Material)c.BlockMaterial).RendersAtAll())
                        {
                            BlockInternal def = new BlockInternal(0, 0, 0, 0);
                            BlockInternal zp  = z + 1 < ZWidth?GetBlockAt(x, y, z + 1) : def;

                            BlockInternal zm = z > 0 ? GetBlockAt(x, y, z - 1) : def;
                            BlockInternal yp = y + 1 < YWidth?GetBlockAt(x, y + 1, z) : def;

                            BlockInternal ym = y > 0 ? GetBlockAt(x, y - 1, z) : def;
                            BlockInternal xp = x + 1 < XWidth?GetBlockAt(x + 1, y, z) : def;

                            BlockInternal xm  = x > 0 ? GetBlockAt(x - 1, y, z) : def;
                            bool          rAS = !((Material)c.BlockMaterial).GetCanRenderAgainstSelf();
                            bool          zps = (zp.IsOpaque() || (rAS && (zp.BlockMaterial == c.BlockMaterial))) && BlockShapeRegistry.BSD[zp.BlockData].OccupiesBOTTOM();
                            bool          zms = (zm.IsOpaque() || (rAS && (zm.BlockMaterial == c.BlockMaterial))) && BlockShapeRegistry.BSD[zm.BlockData].OccupiesTOP();
                            bool          xps = (xp.IsOpaque() || (rAS && (xp.BlockMaterial == c.BlockMaterial))) && BlockShapeRegistry.BSD[xp.BlockData].OccupiesXM();
                            bool          xms = (xm.IsOpaque() || (rAS && (xm.BlockMaterial == c.BlockMaterial))) && BlockShapeRegistry.BSD[xm.BlockData].OccupiesXP();
                            bool          yps = (yp.IsOpaque() || (rAS && (yp.BlockMaterial == c.BlockMaterial))) && BlockShapeRegistry.BSD[yp.BlockData].OccupiesYM();
                            bool          yms = (ym.IsOpaque() || (rAS && (ym.BlockMaterial == c.BlockMaterial))) && BlockShapeRegistry.BSD[ym.BlockData].OccupiesYP();
                            Vector3       pos = new Vector3(x, y, z);
                            List <BEPUutilities.Vector3> vecsi  = BlockShapeRegistry.BSD[c.BlockData].GetVertices(pos, xps, xms, yps, yms, zps, zms);
                            List <BEPUutilities.Vector3> normsi = BlockShapeRegistry.BSD[c.BlockData].GetNormals(pos, xps, xms, yps, yms, zps, zms);
                            List <BEPUutilities.Vector3> tci    = BlockShapeRegistry.BSD[c.BlockData].GetTCoords(pos, (Material)c.BlockMaterial, xps, xms, yps, yms, zps, zms);
                            int vertcount = Vertices.Count;
                            for (int i = 0; i < vecsi.Count; i++)
                            {
                                // TODO: is PosMultiplier used correctly here?
                                OpenTK.Vector3 vt = new OpenTK.Vector3((float)vecsi[i].X, (float)vecsi[i].Y, (float)vecsi[i].Z);
                                Vertices.Add(vt);
                                OpenTK.Vector3 nt = new OpenTK.Vector3((float)normsi[i].X, (float)normsi[i].Y, (float)normsi[i].Z);
                                Normals.Add(nt);
                                TexCoords.Add(new OpenTK.Vector3((float)tci[i].X, (float)tci[i].Y, (float)tci[i].Z));
                                Colrs.Add(new OpenTK.Vector4(1, 1, 1, 1));
                                TCOLs.Add(TheClient.Rendering.AdaptColor(vt, Colors.ForByte(c.BlockPaint)));
                            }
                            for (int i = 0; i < vecsi.Count; i += 3)
                            {
                                int            basis   = vertcount + i;
                                OpenTK.Vector3 v1      = Vertices[basis];
                                OpenTK.Vector3 dv1     = Vertices[basis + 1] - v1;
                                OpenTK.Vector3 dv2     = Vertices[basis + 2] - v1;
                                OpenTK.Vector3 t1      = TexCoords[basis];
                                OpenTK.Vector3 dt1     = TexCoords[basis + 1] - t1;
                                OpenTK.Vector3 dt2     = TexCoords[basis + 2] - t1;
                                OpenTK.Vector3 tangent = (dv1 * dt2.Y - dv2 * dt1.Y) * 1f / (dt1.X * dt2.Y - dt1.Y * dt2.X);
                                OpenTK.Vector3 normal  = Normals[basis];
                                tangent = (tangent - normal * OpenTK.Vector3.Dot(normal, tangent)).Normalized();
                                Tangs.Add(tangent);
                                Tangs.Add(tangent);
                                Tangs.Add(tangent);
                            }
                            if (!c.IsOpaque() && BlockShapeRegistry.BSD[c.BlockData].BackTextureAllowed)
                            {
                                int tf = Colrs.Count - vecsi.Count;
                                for (int i = vecsi.Count - 1; i >= 0; i--)
                                {
                                    Vertices.Add(new OpenTK.Vector3((float)vecsi[i].X, (float)vecsi[i].Y, (float)vecsi[i].Z));
                                    int tx = tf + i;
                                    Colrs.Add(Colrs[tx]);
                                    TCOLs.Add(TCOLs[tx]);
                                    Normals.Add(new OpenTK.Vector3(-(float)normsi[i].X, -(float)normsi[i].Y, -(float)normsi[i].Z));
                                    TexCoords.Add(new OpenTK.Vector3((float)tci[i].X, (float)tci[i].Y, (float)tci[i].Z));
                                }
                            }
                        }
                    }
                }
            }
            if (vbo != null)
            {
                vbo.Destroy();
                vbo = null;
            }
            if (Vertices.Count == 0)
            {
                return;
            }
            vbo      = new VBO();
            vbo.THVs = new List <OpenTK.Vector4>();
            vbo.THWs = new List <OpenTK.Vector4>();
            List <uint> Indices = new List <uint>(Vertices.Count);

            for (uint i = 0; i < Vertices.Count; i++)
            {
                Indices.Add(i);
                vbo.THVs.Add(new OpenTK.Vector4(0, 0, 0, 0));
                vbo.THWs.Add(new OpenTK.Vector4(0, 0, 0, 0));
            }
            vbo.Vertices  = Vertices;
            vbo.Normals   = Normals;
            vbo.TexCoords = TexCoords;
            vbo.Colors    = Colrs;
            vbo.TCOLs     = TCOLs;
            vbo.Tangents  = Tangs;
            vbo.Indices   = Indices;
            vbo.GenerateVBO();
        }