Ejemplo n.º 1
0
    public TestModelEnvironment()
    {
        var printComponents = new HashSet <ModelComponent>();
        var print           = new ModelBlock(new Vector3(10, 10, 10), printComponents, "print");
        var printAccessor   = new ModelComponent(ComponentType.Accessor, new Vector3(10, 10, 15), print);
        var printReturn     = new ModelComponent(ComponentType.Return, new Vector3(10, 10, 5), print);

        printComponents.Add(printAccessor);
        printComponents.Add(printReturn);
        me.AddBlock(print);

        var originComponents = new HashSet <ModelComponent>();
        var originBlock      = new ModelBlock(new Vector3(0, 0, 0), originComponents, "origin", isOrigin: true);
        var originParameter  = new ModelComponent(ComponentType.Parameter, new Vector3(0, 0, 5), originBlock);
        var originReturn     = new ModelComponent(ComponentType.Return, new Vector3(0, 0, -5), originBlock);

        originComponents.Add(originParameter);
        originComponents.Add(originReturn);
        me.AddBlock(originBlock);

        // LINKS ARE WIP
        // This might not make sense.
        var link = new ModelLink(new Vector3(10, 10, 5), new Vector3(0, 0, -5));

        me.AddLink(link);
    }
Ejemplo n.º 2
0
        protected override bool Parse(BinaryReader inputReader)
        {
            if (!base.Parse(inputReader))
            {
                return(false);
            }

            //NOTE(adm244): check for duplicated header
            Int32 magic = inputReader.PeekInt32();

            if (magic == Signature)
            {
                if (!base.Parse(inputReader))
                {
                    return(false);
                }
            }

            while (!inputReader.EOF())
            {
                ModelBlock block = ModelBlock.ParseBlock(inputReader);
                if (block == null)
                {
                    Debug.Assert(false, "Could not parse a block!");
                    break;
                }

                Blocks.Add(block);
            }

            return(Blocks.Count > 0);
        }
Ejemplo n.º 3
0
        public ScenarioObject(ModelBlock model)
            : this()
        {
            this.Model = model;

            if (model.RenderModel == null)
            {
                return;
            }

            this.CollisionObject = new CollisionObject()
            {
                UserObject     = this,
                CollisionFlags = CollisionFlags.StaticObject,
                CollisionShape = new BoxShape(this.Model.RenderModel.compressionInfo[0].ToHalfExtents())
            };

            collisionSpaceMatrix = Matrix4.CreateTranslation(this.Model.RenderModel.compressionInfo[0].ToExtentsMatrix().ExtractTranslation());
            worldMatrix          = Matrix4.Identity;

            foreach (var section in model.RenderModel.sections)
            {
                base.sectionBuffers.Add(new Mesh(section.sectionData[0].section));
            }
            this.Nodes   = new NodeCollection(model.RenderModel.nodes);
            this.Markers = model.RenderModel.markerGroups.SelectMany(x => x.Markers).ToDictionary(x => x, x => new MarkerWrapper(x, this.Nodes));
        }
Ejemplo n.º 4
0
    public static HashSet <ModelBlock> GetSampleModelBlocks()
    {
        var multiplyBlock = new ModelBlock(new Vector3(10, 5, 0), new HashSet <ModelComponent> {
        }, "multiply");

        var multiplyParameter1 = new ModelComponent(ComponentType.Parameter, new Vector3(10, 7, 0), multiplyBlock, id: "p1", initializeValue: 2);
        var multiplyParameter2 = new ModelComponent(ComponentType.Parameter, new Vector3(10, 8, 0), multiplyBlock, id: "p2", initializeValue: 3);
        var multiplyReturn     = new ModelComponent(ComponentType.Return, new Vector3(8, 5, 0), multiplyBlock);

        multiplyBlock.AddComponent(multiplyParameter1);
        multiplyBlock.AddComponent(multiplyParameter2);
        multiplyBlock.AddComponent(multiplyReturn);


        var originBlock = new ModelBlock(new Vector3(3, 3, 0), new HashSet <ModelComponent> {
        }, "hello", isOrigin: true);

        var originReturn = new ModelComponent(ComponentType.Return, new Vector3(5, 5, 0), originBlock);

        originBlock.AddComponent(originReturn);

        return(new HashSet <ModelBlock> {
            multiplyBlock, originBlock
        });
    }
Ejemplo n.º 5
0
    public void ConstructAndBindViewComponent(ViewComponent vc, ModelBlock parent)
    {
        var modelPosition = new Vector3(vc.Position.x, vc.Position.y, vc.Position.z);
        var mc            = new ModelComponent(vc.componentType, modelPosition, parent);
        var binding       = new ComponentBinding(vc, mc, environmentChanged);

        componentBindings.Add(binding);
        me.AddComponent(mc);
    }
Ejemplo n.º 6
0
 public ModelComponent(ComponentType componentType, Vector3 position, ModelBlock parent, string id = null, int?initializeValue = null)
 {
     this.componentType   = componentType;
     this.Position        = position;
     this.links           = new HashSet <ModelLink>();
     this.parent          = parent;
     this.Id              = id;
     this.InitializeValue = initializeValue;
 }
        public ParticleDigging(World world, Vector3 pos, Vector3 motion, float particleScale, BlockState state, FaceSides side) : base(world, pos, motion, particleScale, JsonModelLoader.TEXTURE_BLOCKS)
        {
            State = state;

            ModelBlock model = JsonModelLoader.GetModelForBlock(state.Block.UnlocalizedName);

            if (model.RawModel is ModelBlockRaw mbr)
            {
                Vector2 start;
                Vector2 end;

                if (state.Block.IsFullCube)
                {
                    List <float> uvs = new List <float>(8);
                    mbr.AppendUvsForSide(side, uvs);

                    start = new Vector2(uvs[0], uvs[1]);
                    end   = new Vector2(uvs[4], uvs[5]); //4,5 because that's the 3. vertex and the local UV there is 1,1
                }
                else
                {
                    var tex = model.GetParticleTexture();

                    start = tex.UVMin;
                    end   = tex.UVMax;
                }

                Vector2 size = end - start;

                Vector2 pixel = size / 16;

                UVmin = start + pixel * new Vector2(MathUtil.NextFloat(0, 12), MathUtil.NextFloat(0, 12));
                UVmax = UVmin + pixel * 4;
            }

            if (side == FaceSides.Up)
            {
                Motion.Xz = SharpCraft.Instance.Camera.GetLookVec().Xz * 0.15f;
            }

            Vector3 vec = new Vector3(MathUtil.NextFloat(-1), MathUtil.NextFloat(-1), MathUtil.NextFloat(-1));

            _rotStep = vec.Normalized() * MathUtil.NextFloat(40, 75);
        }
Ejemplo n.º 8
0
    public ModelBlock ConvertViewBlockToModelBlock(GameObject gameObjectViewBlock)
    {
        HashSet <ModelComponent> modelComponents = new HashSet <ModelComponent>();
        Vector3 viewPosition     = gameObjectViewBlock.transform.position;
        string  viewName         = gameObjectViewBlock.GetComponent <ViewBlock>().id;
        var     resultModelBlock = new ModelBlock(viewPosition, modelComponents, viewName);

        foreach (ViewComponent vc in gameObjectViewBlock.GetComponentsInChildren <ViewComponent>())
        {
            var mc      = new ModelComponent(vc.componentType, vc.Position, resultModelBlock);
            var binding = new ComponentBinding(vc, mc, environmentChanged);
            vc.Initialize(gameObjectViewBlock.GetComponent <ViewBlock>(), binding);
            modelComponents.Add(mc);
            componentBindings.Add(binding);
            me.AddComponent(mc);
        }

        return(resultModelBlock);
    }
Ejemplo n.º 9
0
 /// <summary>
 ///     Calculates the DetailLevel
 /// </summary>
 /// <param name="modelBlock">ModelBlock to select detail level from</param>
 /// <param name="distance">Distance from viewer to object</param>
 /// <returns>DetailLevel value from Level1 to Level6</returns>
 private static DetailLevel GetDetailLevel(ModelBlock modelBlock, float distance)
 {
     if (distance > modelBlock.ReduceToL1)
     {
         return(DetailLevel.Level1);
     }
     if (distance > modelBlock.ReduceToL2)
     {
         return(DetailLevel.Level2);
     }
     if (distance > modelBlock.ReduceToL3)
     {
         return(DetailLevel.Level3);
     }
     if (distance > modelBlock.ReduceToL4)
     {
         return(DetailLevel.Level4);
     }
     return(distance > modelBlock.ReduceToL5 ? DetailLevel.Level5 : DetailLevel.Level6);
 }
Ejemplo n.º 10
0
        public ScenarioObject(ModelBlock model)
            : this()
        {
            Model = model;
            if (!model.TryGetCacheKey(out _key))
            {
                return;
            }

            RenderModel = ( RenderModelBlock )model.RenderModel.Get(_key);

            if (RenderModel == null)
            {
                CollisionObject = new ClickableCollisionObject
                {
                    UserObject     = this,
                    CollisionFlags = CollisionFlags.StaticObject,
                    CollisionShape = new BoxShape(0)
                };
                return;
            }
            else
            {
                CollisionObject = new ClickableCollisionObject
                {
                    UserObject     = this,
                    CollisionFlags = CollisionFlags.StaticObject,
                    CollisionShape = new BoxShape(RenderModel.CompressionInfo[0].ToHalfExtents( ))
                };
            }

            collisionSpaceMatrix =
                Matrix4.CreateTranslation(
                    RenderModel.CompressionInfo[0].ToObjectMatrix( ).ExtractTranslation( ));
            _worldMatrix = Matrix4.Identity;

            LoadSections(5);
            RenderBatches = GetRenderBatches();

            Nodes = new List <RenderModelNodeBlock>(RenderModel.Nodes);
        }
Ejemplo n.º 11
0
 public void RemoveBlock(ModelBlock mb)
 {
     blocks.Remove(mb);
 }
Ejemplo n.º 12
0
 public void AddBlock(ModelBlock mb)
 {
     blocks.Add(mb);
 }
Ejemplo n.º 13
0
 public Binding(ViewBlock vb, ModelBlock mb, UnityEvent viewModelEvent)
 {
     this.vb            = vb;
     this.mb            = mb;
     environmentChanged = viewModelEvent;
 }
Ejemplo n.º 14
0
 public BlockState(Block block, ModelBlock model)
 {
     Block = block;
     Model = model;
 }
Ejemplo n.º 15
0
        public override void Render(float partialTicks)
        {
            Vector3 partialPos  = LastPos + (Pos - LastPos) * partialTicks;
            float   partialTime = _ticksLast + (_ticks - _ticksLast) * partialTicks;

            if (_stack == null || _stack.IsEmpty)
            {
                return;
            }

            float   offY = (float)((Math.Sin(partialTime / 90f * MathHelper.TwoPi) + 1) / 16);
            Vector3 vec  = Vector3.One * 0.5f;
            Vector3 pos  = partialPos - (Vector3.UnitX * 0.125f + Vector3.UnitZ * 0.125f) + Vector3.UnitY * offY;
            Matrix4 rot  = Matrix4.CreateRotationY(partialTime / 90f * MathHelper.TwoPi);
            Matrix4 t2   = Matrix4.CreateTranslation(-vec);

            if (_stack.Item is ItemBlock itemBlock)
            {
                ModelBlock model = itemBlock.Block.GetState(_stack.Meta).Model;

                if (model?.RawModel == null)
                {
                    return;
                }

                Shader.Bind();
                Shader.SetFloat("fogDistance", SharpCraft.Instance.WorldRenderer.RenderDistance);

                GL.BindVertexArray(model.RawModel.VaoID);

                GL.EnableVertexAttribArray(0);
                GL.EnableVertexAttribArray(1);
                GL.EnableVertexAttribArray(2);

                GL.BindTexture(TextureTarget.Texture2D, JsonModelLoader.TextureBlocks);

                int itemsToRender = 1;

                if (_stack.Count > 1)
                {
                    itemsToRender = 2;
                }
                if (_stack.Count >= 32 * 4)
                {
                    itemsToRender = 3;
                }
                if (_stack.Count == 64 * 4)
                {
                    itemsToRender = 4;
                }

                for (int i = 0; i < itemsToRender; i++)
                {
                    Vector3 posO = Vector3.One * (i / 8f);

                    Matrix4 s = Matrix4.CreateScale(0.25f);
                    Matrix4 t = Matrix4.CreateTranslation(pos + vec * 0.25f);

                    Matrix4 t3 = Matrix4.CreateTranslation(posO);

                    Matrix4 mat = t3 * t2 * (rot * s) * t;

                    Shader.SetMatrix4("transformationMatrix", mat);

                    model.RawModel.Render();
                }

                GL.BindVertexArray(0);

                GL.DisableVertexAttribArray(0);
                GL.DisableVertexAttribArray(1);
                GL.DisableVertexAttribArray(2);

                Shader.Unbind();
            }
            else
            {
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
                GL.Disable(EnableCap.CullFace);
                ModelItem model = JsonModelLoader.GetModelForItem(_stack.Item);

                if (model?.RawModel == null)
                {
                    return;
                }

                Shader.Bind();

                GL.BindVertexArray(model.RawModel.VaoID);

                GL.EnableVertexAttribArray(0);
                GL.EnableVertexAttribArray(1);
                GL.EnableVertexAttribArray(2);

                GL.BindTexture(TextureTarget.Texture2D, JsonModelLoader.TextureItems);

                int itemsToRender = 1;

                if (_stack.Count > 1)
                {
                    itemsToRender = 2;
                }
                if (_stack.Count >= 32 * 4)
                {
                    itemsToRender = 3;
                }
                if (_stack.Count == 64 * 4)
                {
                    itemsToRender = 4;
                }

                for (int i = 0; i < itemsToRender; i++)
                {
                    Vector3 posO = Vector3.One * (i / 8f);

                    Matrix4 s  = Matrix4.CreateScale(0.35f);
                    Matrix4 t  = Matrix4.CreateTranslation(pos + vec * 0.35f);
                    Matrix4 t3 = Matrix4.CreateTranslation(posO);

                    Matrix4 mat = t3 * t2 * (rot * s) * t;

                    Shader.SetMatrix4("transformationMatrix", mat);
                    model.RawModel.Render();
                }

                GL.BindVertexArray(0);

                GL.DisableVertexAttribArray(0);
                GL.DisableVertexAttribArray(1);
                GL.DisableVertexAttribArray(2);

                Shader.Unbind();
                GL.Enable(EnableCap.CullFace);
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            }
        }
Ejemplo n.º 16
0
 public ScenarioObjectd(ModelBlock test)
 {
     this.model        = test;
     ActivePermutation = StringID.Zero;
 }
Ejemplo n.º 17
0
 private void AddToModel(ModelBlock modelBlock)
 {
     me.AddBlock(modelBlock);
 }
Ejemplo n.º 18
0
        public override void Render(float partialTicks)
        {
            Vector3 partialPos  = LastPos + (Pos - LastPos) * partialTicks;
            float   partialTime = tick + partialTicks;

            if (stack?.Item is ItemBlock itemBlock)
            {
                ModelBlock model = JsonModelLoader.GetModelForBlock(itemBlock.Block.UnlocalizedName);

                if (model == null || model.RawModel == null)
                {
                    return;
                }

                float time = onGround ? (float)((Math.Sin(partialTime / 8) + 1) / 16) : 0;

                _shader.Bind();

                GL.BindVertexArray(model.RawModel.VaoID);

                GL.EnableVertexAttribArray(0);
                GL.EnableVertexAttribArray(1);
                GL.EnableVertexAttribArray(2);

                GL.BindTexture(TextureTarget.Texture2D, JsonModelLoader.TEXTURE_BLOCKS);

                int itemsToRender = 1;

                if (stack.Count > 1)
                {
                    itemsToRender = 2;
                }
                if (stack.Count >= 32 * 4)
                {
                    itemsToRender = 3;
                }
                if (stack.Count == 64 * 4)
                {
                    itemsToRender = 4;
                }

                for (int i = 0; i < itemsToRender; i++)
                {
                    Vector3 rot   = Vector3.UnitY * partialTime * 3;
                    Vector3 pos   = partialPos - (Vector3.UnitX * 0.125f + Vector3.UnitZ * 0.125f) + Vector3.UnitY * time;
                    Vector3 pos_o = Vector3.One * (i / 8f);

                    Matrix4 x = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(rot.X));
                    Matrix4 y = Matrix4.CreateRotationY(MathHelper.DegreesToRadians(rot.Y));
                    Matrix4 z = Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(rot.Z));

                    Vector3 vec = Vector3.One * 0.5f;

                    Matrix4 s  = Matrix4.CreateScale(0.25f);
                    Matrix4 t  = Matrix4.CreateTranslation(pos + vec * 0.25f);
                    Matrix4 t2 = Matrix4.CreateTranslation(-vec);
                    Matrix4 t3 = Matrix4.CreateTranslation(pos_o);

                    Matrix4 mat = t3 * t2 * (z * y * x * s) * t;

                    _shader.UpdateGlobalUniforms();
                    _shader.UpdateModelUniforms(model.RawModel);
                    _shader.UpdateInstanceUniforms(mat, this);
                    model.RawModel.Render(PrimitiveType.Quads);
                }

                GL.BindVertexArray(0);

                GL.DisableVertexAttribArray(0);
                GL.DisableVertexAttribArray(1);
                GL.DisableVertexAttribArray(2);

                _shader.Unbind();
            }
        }
Ejemplo n.º 19
0
        public void LoadBlockModels()
        {
            string modelsDir      = $"{SharpCraft.Instance.GameFolderDir}/assets/sharpcraft/models";
            string blockModelsDir = $"{modelsDir}/block";
            string blockStatesDir = $"{modelsDir}/block/states";

            var listOfBlocks = BlockRegistry.AllBlocks();

            var nonDuplicateTextures = new List <string>();

            var blockModels = new ConcurrentDictionary <string, List <List <JsonModel> > >();

            foreach (var block in listOfBlocks)              // for each Block that's been registered
            {
                var states = new List <List <JsonModel> >(); //save state models for each block
                blockModels.TryAdd(block.UnlocalizedName, states);

                string        unlocalizedLast = LangUtil.GetUnlocalizedNameLast(block.UnlocalizedName);
                List <string> stateFiles      = new List <string> {
                    $"{blockModelsDir}/{unlocalizedLast}.json"
                };

                string statesFile = $"{blockStatesDir}/{unlocalizedLast}.json";

                if (File.Exists(statesFile))
                {
                    try
                    {
                        string          json = File.ReadAllText(statesFile);
                        JsonBlockStates jbs  = JsonConvert.DeserializeObject <JsonBlockStates>(json);

                        if (jbs.states != null)
                        {
                            foreach (var modelFileName in jbs.states)
                            {
                                var stateFile = $"{modelsDir}/{modelFileName.model}.json";

                                if (File.Exists(stateFile))
                                {
                                    stateFiles.Add(stateFile);
                                }
                            }
                        }
                    }
                    catch
                    {
                    }
                }

                foreach (var stateFile in stateFiles)
                {
                    //load state
                    var models = LoadModel(stateFile, "particle");

                    foreach (var jsonModel in models)
                    {
                        if (jsonModel.textures == null)
                        {
                            continue;
                        }

                        foreach (var textureName in jsonModel.textures.Values) //iterating over the textureMap in the Json model
                        {
                            if (!nonDuplicateTextures.Contains(textureName))
                            {
                                nonDuplicateTextures.Add(textureName); //add the current texture name to a list of all textureMap if isn't already there
                            }
                        }
                    }

                    states.Add(models);
                }
            }

            //each texture name has it's UV values TODO - maybe make a TextureMap class where this could be used
            var id = Stitch(nonDuplicateTextures.ToArray(), 16, out var textureMapElements); // stitch all textureMap, return the texture ID of the registered texture in VRAM

            //TODO - if json doesn't contain cube model, assume it's a full cube
            foreach (var pair in blockModels) //one model per registered item
            {
                string blockName = pair.Key;

                var states = new List <ModelBlock>();

                foreach (var state in pair.Value)
                {
                    List <float> vertexes = new List <float>();
                    List <float> normals  = new List <float>();
                    List <float> uvs      = new List <float>();

                    List <JsonCube> cubes = new List <JsonCube>();

                    Dictionary <string, string> textures = new Dictionary <string, string>();

                    foreach (var jsonModel in state)
                    {
                        foreach (var cube in jsonModel.cubes)
                        {
                            cubes.Add(cube);
                        }

                        if (jsonModel.textures == null)
                        {
                            continue;
                        }

                        foreach (var pairtex in jsonModel.textures)
                        {
                            textures.Remove(pairtex.Key);
                            textures.Add(pairtex.Key, pairtex.Value);
                        }
                    }

                    foreach (var cube in cubes)
                    {
                        CubeModelBuilder.AppendCubeModel(cube, textures, textureMapElements, ref vertexes,
                                                         ref normals, ref uvs);
                    }

                    if (!textures.TryGetValue("particle", out var particleTexture))
                    {
                        particleTexture = textures.Values.ToArray()[SharpCraft.Instance.Random.Next(0, textures.Count)];
                    }
                    if (!textures.TryGetValue("item", out var slotTexture))
                    {
                        if (cubes.Count > 0 && cubes[0].faces.TryGetValue(Facing.south, out var uv))
                        {
                            slotTexture = textures[uv.texture];
                        }
                    }

                    var particleTme = textureMapElements[particleTexture];
                    var slotTme     = textureMapElements.TryGetValue(slotTexture ?? "", out var result)
                        ? result
                        : particleTme;

                    ModelBlock mb = new ModelBlock(slotTme, particleTme, _blockShader, ModelManager.LoadBlockModelToVao(vertexes.ToArray(), normals.ToArray(), uvs.ToArray()));

                    states.Add(mb);
                }

                BlockStateModels.TryAdd(blockName, states);
            }

            TextureBlocks = id;
        }
Ejemplo n.º 20
0
        public void BuildChunkModelNow()
        {
            if (ModelBuilding || !QueuedForModelBuild)
            {
                return;
            }

            ModelBuilding = true;

            //ConcurrentDictionary<Shader<ModelBlock>, List<RawQuad>> modelRaw = new ConcurrentDictionary<Shader<ModelBlock>, List<RawQuad>>();

            //List<RawQuad> quads;

            Stopwatch sw = Stopwatch.StartNew(); //this is just a debug thing....

            var air = BlockRegistry.GetBlock <BlockAir>();

            var vertexes = new List <float>();
            var normals  = new List <float>();
            var uvs      = new List <float>();

            object locker = new object();

            //generate the model - fill MODEL_RAW
            Enumerable.Range(0, ChunkHeight).AsParallel().ForAll(y =>
            {
                for (int x = 0; x < ChunkSize; x++)
                {
                    for (int z = 0; z < ChunkSize; z++)
                    {
                        BlockPos worldPos = new BlockPos(x + Pos.WorldSpaceX(), y, z + Pos.WorldSpaceZ());

                        BlockState state = World.GetBlockState(worldPos);
                        if (state.Block == air)
                        {
                            continue;
                        }

                        BlockPos localPos = new BlockPos(x, y, z);

                        ModelBlock model  = JsonModelLoader.GetModelForBlock(state.Block.UnlocalizedName);
                        ModelBlockRaw mbr = (ModelBlockRaw)model?.RawModel;

                        if (mbr == null)
                        {
                            continue;
                        }

                        if (!state.Block.IsFullCube)
                        {
                            lock (locker)
                                mbr.AppendAllVertexData(vertexes, normals, uvs, localPos);

                            continue;
                        }

                        for (var index = 0; index < FaceSides.AllSides.Count; index++)
                        {
                            FaceSides dir = FaceSides.AllSides[index];

                            BlockPos worldPosO = worldPos.Offset(dir);
                            BlockState stateO  = World.GetBlockState(worldPosO);

                            if (!(stateO.Block == air ||
                                  stateO.Block.HasTransparency && !state.Block.HasTransparency) &&
                                stateO.Block.IsFullCube)
                            {
                                continue;
                            }

                            lock (locker)
                            {
                                mbr.AppendVertexDataForSide(dir, vertexes, normals, uvs, localPos);
                                //mbr.AppendNormalsForSide(dir, normals);
                                //mbr.AppendUvsForSide(dir, uvs);
                            }
                        }
                    }
                }
            });

            sw.Stop();
            Console.WriteLine($"DEBUG: built chunk model [{sw.Elapsed.TotalMilliseconds:F}ms]");

            float[] vtx = vertexes.ToArray(); //this is here because this takes time and I don't want it to slow down the main thread by running it in GlContext
            float[] nrm = normals.ToArray();
            float[] uv  = uvs.ToArray();

            SharpCraft.Instance.RunGlContext(() =>
            {
                if (_model == null)
                {
                    _model = new ModelChunk(vtx, nrm, uv, Block.DefaultShader);
                }
                else
                {
                    _model.OverrideData(vtx, nrm, uv);
                }

                ModelBuilding = false;
            });

            QueuedForModelBuild = false;
        }