Example #1
0
        // Ignore, doesn't work. Bad.
        private static Vector3 EulerAnglesFromQuat(Quaternion q)
        {
            float singularityTest      = q.Z * q.X - q.W * q.Y;
            float yawY                 = 2f * (q.W * q.Z + q.X * q.Y);
            float yawX                 = (float)(1f - 2f * (Math.Pow(q.Y, 2) + Math.Pow(q.Z, 2)));
            float singularityThreshold = 0.4999995f;

            Vector3 eulerAngles = Vector3.Zero;

            if (singularityTest < singularityThreshold)
            {
                eulerAngles.X = -90f;
                eulerAngles.Y = (float)Math.Atan2(yawY, yawX);
                eulerAngles.Z = WMath.Clamp(-eulerAngles.Y - (2f * (float)Math.Atan2(q.X, q.W)), (float)-Math.PI, (float)Math.PI);
            }
            else if (singularityTest > singularityThreshold)
            {
                eulerAngles.X = 90;
                eulerAngles.Y = (float)Math.Atan2(yawY, yawX);
                eulerAngles.Z = WMath.Clamp(eulerAngles.Y - (2f * (float)Math.Atan2(q.X, q.W)), (float)-Math.PI, (float)Math.PI);
            }
            else
            {
                eulerAngles.X = (float)Math.Asin(2f * (singularityTest));
                eulerAngles.Y = (float)Math.Atan2(yawY, yawX);
                eulerAngles.Z = (float)Math.Atan2(-2f * (q.W * q.X + q.Y * q.Z), (1f - 2f * (Math.Pow(q.X, 2) + Math.Pow(q.Y, 2))));
            }

            return(eulerAngles);
        }
Example #2
0
        private void CameraRotation()
        {
            Vector2D deltas = Input.MouseDelta;

            double ax = (Angles.X + (deltas.X * Input.MouseSensivity * Time.DeltaTime)) % 360.0D;
            double ay = WMath.Clamp((Angles.Y + (deltas.Y * Input.MouseSensivity * Time.DeltaTime)), -89.9D, 89.9D);

            Angles = new Vector2D(ax, ay);

            this.FPSCamera.WObject.Rotation = new Engine.Quaternion(-ay, ax, 0.0F);
        }
        private void DoApplicationTick()
        {
            // Poll the mouse at a high resolution
            System.Drawing.Point mousePos = m_glControl.PointToClient(System.Windows.Forms.Cursor.Position);

            mousePos.X = WMath.Clamp(mousePos.X, 0, m_glControl.Width);
            mousePos.Y = WMath.Clamp(mousePos.Y, 0, m_glControl.Height);
            WInput.SetMousePosition(new Vector2(mousePos.X, mousePos.Y));

            ProcessTick();
            WInput.Internal_UpdateInputState();

            m_glControl.SwapBuffers();
        }
Example #4
0
        private void AnimateDisplayName()
        {
            ItemNameCooldown -= Time.Delta;

            if (ItemNameCooldown < 0.0)
            {
                ItemNameLabel.Enabled = false;
            }
            else if (ItemNameCooldown < ItemNameTime)
            {
                Color256 col = ItemNameLabel.Color;
                col.A = WMath.Clamp(ItemNameCooldown / ItemNameDisappearTime, 0, 1);
                ItemNameLabel.Color = col;
            }
        }
Example #5
0
        public void AnimateWalk(Vector3D velocity)
        {
            if (PlayerLeftLeg == null || PlayerRightLeg == null)
            {
                return;
            }
            double speed = WMath.Clamp(velocity.XZ.Length, 0, Player.WalkSpeed);

            CurrentWalkAnimationTime += Time.Delta * speed * WalkAnimationSpeedCoef;

            double t = WMath.Remap(Math.Cos(CurrentWalkAnimationTime), -1, 1, 0, 1);

            double speedCoef = speed <= 0.05D ? 0.0D : speed / Player.WalkSpeed;

            double currentAngle = WMath.Lerp(-WalkAnimationMaxAngle * speedCoef, WalkAnimationMaxAngle * speedCoef, t);//WMath.Remap(CurrentWalkAnimationTime, 0, 1, -WalkAnimationMaxAngle * speedCoef, WalkAnimationMaxAngle * speedCoef);


            Quaternion leftRotLeg  = new Quaternion(-currentAngle * WalkAnimationLegCoef, 0, 0);
            Quaternion rightRotLeg = new Quaternion(currentAngle * WalkAnimationLegCoef, 0, 0);

            Quaternion rightRotArm = new Quaternion(-currentAngle, 0, 0);
            Quaternion leftRotArm  = new Quaternion(currentAngle, 0, 0);


            PlayerLeftLeg.LocalRotation  = leftRotLeg;
            PlayerRightLeg.LocalRotation = rightRotLeg;

            PlayerRightArm.LocalRotation *= rightRotArm;
            PlayerLeftArm.LocalRotation  *= leftRotArm;


            Vector3D flattenVel   = new Vector3D(velocity.X, 0, velocity.Z);
            Vector3D flattenDir   = flattenVel.Normalized;
            double   flattenSpeed = flattenVel.Length;

            if (flattenSpeed >= 0.1D)
            {
                double currentTorsoAngle = Quaternion.AngleY(PlayerTorso.Rotation, Quaternion.Identity);
                double rawNewAngle       = (Math.Atan2(flattenDir.X, flattenDir.Z) * WMath.RadToDeg) * -1;

                double deltaAngle = WMath.DeltaAngle(currentTorsoAngle, rawNewAngle);

                deltaAngle = WMath.Clamp(deltaAngle, -HeadMaxAngleToBody, HeadMaxAngleToBody);

                PlayerTorso.LocalRotation *= new Quaternion(0, -deltaAngle * WalkAnimationTorsoOrientCoef * Time.Delta, 0);
            }
        }
Example #6
0
        public static void GlobalToLocal(Vector3F global, out Vector3I ChunkPosition, out Vector3I LocalPosition)
        {
            ChunkPosition = new Vector3I(
                ((int)global.X / Chunk.Width) + (global.X < 0.0F ? -1 : 0), //X position
                ((int)global.Z / Chunk.Depth) + (global.Z < 0.0F ? -1 : 0), //Y position
                0);                                                         //Z dimension

            float localX = global.X % Chunk.Width;

            if (localX < 0)
            {
                localX += Chunk.Width;
            }

            float localZ = global.Z % Chunk.Depth;

            if (localZ < 0)
            {
                localZ += Chunk.Depth;
            }

            LocalPosition = new Vector3I((int)localX, WMath.Clamp((int)global.Y, 0, 255), (int)localZ);
        }
        private void RenderFrame()
        {
            m_frameBuffer.Bind();
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
            GL.Viewport(0, 0, m_frameBuffer.Width, m_frameBuffer.Height);

            float deltaTime = m_dtStopwatch.ElapsedMilliseconds / 1000f;

            m_dtStopwatch.Restart();
            m_renderCamera.Tick(deltaTime);
            m_lineBatcher.Tick(deltaTime);
            m_skeletonLineBatcher.Tick(deltaTime);

            deltaTime           = WMath.Clamp(deltaTime, 0, 0.25f); // quarter second max because debugging
            m_timeSinceStartup += deltaTime;

            if (m_modelRenderOptions.AnimateLight)
            {
                // Rotate our light
                float angleInRad = m_timeSinceStartup % WMath.DegreesToRadians(360f);
                m_mainLight.Position = new Vector4(CalculateLightPosition(angleInRad), 0);
            }

            if (m_modelRenderOptions.ShowGrid)
            {
                DrawFixedGrid();
            }

            if (m_modelRenderOptions.DepthPrePass)
            {
                foreach (var j3d in m_loadedModels)
                {
                    // Render a depth-only pre pass. We need to tell it to render translucent and opaque objects so that
                    // they both write in to the depth buffer (it's a specific pre-pass so they should)
                    j3d.Render(m_renderCamera.ViewMatrix, m_renderCamera.ProjectionMatrix, Matrix4.Identity, true, true, true);
                }
            }

            foreach (var j3d in m_loadedModels)
            {
                j3d.Tick(deltaTime);
            }

            foreach (var j3d in m_loadedModels)
            {
                j3d.SetHardwareLight(0, m_mainLight);
                j3d.Render(m_renderCamera.ViewMatrix, m_renderCamera.ProjectionMatrix, Matrix4.Identity, true, false);
            }
            foreach (var j3d in m_loadedModels)
            {
                // Do a second render pass after all objects to render translucent ones.
                j3d.Render(m_renderCamera.ViewMatrix, m_renderCamera.ProjectionMatrix, Matrix4.Identity, false, true);
            }

            if (m_modelRenderOptions.ShowPivot)
            {
                m_lineBatcher.DrawLine(Vector3.Zero, new Vector3(50, 0, 0), WLinearColor.Red, 0, 0);
                m_lineBatcher.DrawLine(Vector3.Zero, new Vector3(0, 50, 0), WLinearColor.Green, 0, 0);
                m_lineBatcher.DrawLine(Vector3.Zero, new Vector3(0, 0, 50), WLinearColor.Blue, 0, 0);
            }

            if (m_modelRenderOptions.ShowBoundingBox)
            {
                foreach (var j3d in m_loadedModels)
                {
                    j3d.DrawBoundsForShapes(true, false, m_lineBatcher);
                }
            }

            if (m_modelRenderOptions.ShowBoundingSphere)
            {
                foreach (var j3d in m_loadedModels)
                {
                    j3d.DrawBoundsForShapes(false, true, m_lineBatcher);
                }
            }

            if (m_modelRenderOptions.ShowBoneBoundingBox)
            {
                foreach (var j3d in m_loadedModels)
                {
                    j3d.DrawBoundsForJoints(true, false, m_lineBatcher);
                }
            }

            if (m_modelRenderOptions.ShowBoneBoundingSphere)
            {
                foreach (var j3d in m_loadedModels)
                {
                    j3d.DrawBoundsForJoints(false, true, m_lineBatcher);
                }
            }

            if (m_modelRenderOptions.ShowBones)
            {
                foreach (var j3d in m_loadedModels)
                {
                    j3d.DrawBones(m_skeletonLineBatcher);
                }
            }

            // Debug Rendering
            if (WInput.GetKey(Key.I))
            {
                GL.Disable(EnableCap.CullFace);
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactorSrc.DstAlpha, BlendingFactorDest.Zero);

                m_alphaVisualizationShader.Bind();
                m_screenQuad.Draw();
            }

            // Blit the framebuffer to the backbuffer so it shows up on screen.
            m_lineBatcher.Render(m_renderCamera.ViewMatrix, m_renderCamera.ProjectionMatrix);
            m_skeletonLineBatcher.Render(m_renderCamera.ViewMatrix, m_renderCamera.ProjectionMatrix, true);
            m_frameBuffer.BlitToBackbuffer(m_viewportWidth, m_viewportHeight);
        }
Example #8
0
        protected internal override void Update()
        {
            base.Update();

            if (!Hovered && Editing && Input.IsPressing(Keys.MouseLeftButton))
            {
                Editing = false;
                this.OnLeaveEdit?.Invoke();
            }

            if (!Graphics.Window.Focused)
            {
                Editing = false;
            }

            bool textEdited = false;
            int  chars      = Text == null ? 0 : Text.Length;

            KeysModifiers modifiers = Input.GetModifiers();

            if (Editing)
            {
                Keys[] keys = Input.GetAllKeys(KeyStates.Pressing);

                for (int i = 0; i < keys.Length; i++)
                {
                    if (keys[i] != Keys.Back && Text?.Length >= MaxChars)
                    {
                        Text       = Text.Substring(0, MaxChars);
                        textEdited = true;
                        break;
                    }

                    if (keys[i].IsKeyboard() && !keys[i].IsModifier())
                    {
                        if (keys[i] == Keys.Escape || keys[i] == Keys.Enter)
                        {
                            bool stop = true;
                            if (AllowNewLine)
                            {
                                if (modifiers.HasFlag(KeysModifiers.Shift))
                                {
                                    stop       = false;
                                    Text      += "\n";
                                    textEdited = true;
                                }
                            }
                            if (stop)
                            {
                                this.Editing = false;
                                this.OnLeaveEdit?.Invoke();
                                break;
                            }
                        }
                        else if (keys[i] == Keys.Back)
                        {
                            Text       = Text.Substring(0, WMath.Clamp(Text.Length - 1, 0, int.MaxValue));
                            textEdited = true;
                        }
                        else if (keys[i] == Keys.Space)
                        {
                            Text      += " ";
                            textEdited = true;
                        }
                        else if (keys[i] == Keys.Tab)
                        {
                            Text      += "    ";
                            textEdited = true;
                        }
                        else
                        {
                            textEdited = true;
                            Text      += keys[i].ToString(modifiers);
                        }
                    }
                }
            }

            if (_FirstRun || textEdited)
            {
                _FirstRun = false;

                if (!string.IsNullOrEmpty(this.Text))
                {
                    this.Label.Color = this.TextColor;
                    this.Label.Text  = this.Text;
                }
                else
                {
                    this.Label.Color = this.EmptyTextColor;
                    this.Label.Text  = this.EmptyText;
                }
            }

            if (Editing)
            {
                this.IdleColor  = this.EditingColor;
                this.HoverColor = this.EditingColor;
            }

            else
            {
                this.IdleColor  = this.NotEditingColor;
                this.HoverColor = this.TextInputHoverColor;
            }
        }
Example #9
0
        public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, Matrix4 modelMatrix)
        {
            m_viewMatrix  = viewMatrix;
            m_projMatrix  = projectionMatrix;
            m_modelMatrix = modelMatrix;

            IList <SkeletonJoint> boneList = (m_currentBoneAnimation != null) ? JNT1Tag.AnimatedJoints : JNT1Tag.BindJoints;

            Matrix4[] boneTransforms = new Matrix4[boneList.Count];
            ApplyBonePositionsToAnimationTransforms(boneList, boneTransforms);

            // Assume that all bone animations constantly invalidate the skinning.
            if (m_currentBoneAnimation != null)
            {
                m_skinningInvalid = true;
            }

            // We'll only transform the position and normal vertices if skinning has been invalidated.
            if (m_skinningInvalid)
            {
                foreach (var shape in SHP1Tag.Shapes)
                {
                    var transformedPositions = new List <Vector3>(shape.VertexData.Position.Count);
                    var transformedNormals   = new List <Vector3>(shape.VertexData.Normal.Count);
                    //List<WLinearColor> colorOverride = new List<WLinearColor>();

                    for (int i = 0; i < shape.VertexData.Position.Count; i++)
                    {
                        // This is relative to the vertex's original packet's matrix table.
                        ushort posMtxIndex = (ushort)(shape.VertexData.PositionMatrixIndexes[i]);

                        // We need to calculate which packet data table that is.
                        int originalPacketIndex = 0;
                        for (int p = 0; p < shape.MatrixDataTable.Count; p++)
                        {
                            if (i >= shape.MatrixDataTable[p].FirstRelevantVertexIndex && i < shape.MatrixDataTable[p].LastRelevantVertexIndex)
                            {
                                originalPacketIndex = p; break;
                            }
                        }

                        // Now that we know which packet this vertex belongs to, we can get the index from it.
                        // If the Matrix Table index is 0xFFFF then it means "use previous", and we have to
                        // continue backwards until it is no longer 0xFFFF.
                        ushort matrixTableIndex;
                        do
                        {
                            matrixTableIndex = shape.MatrixDataTable[originalPacketIndex].MatrixTable[posMtxIndex];
                            originalPacketIndex--;
                        } while (matrixTableIndex == 0xFFFF);

                        bool   isPartiallyWeighted = DRW1Tag.IsPartiallyWeighted[matrixTableIndex];
                        ushort indexFromDRW1       = DRW1Tag.TransformIndexTable[matrixTableIndex];

                        Matrix4 finalMatrix = Matrix4.Zero;
                        if (isPartiallyWeighted)
                        {
                            EVP1.Envelope envelope = EVP1Tag.Envelopes[indexFromDRW1];
                            for (int b = 0; b < envelope.NumBones; b++)
                            {
                                Matrix4 sm1 = EVP1Tag.InverseBindPose[envelope.BoneIndexes[b]];
                                Matrix4 sm2 = boneTransforms[envelope.BoneIndexes[b]];

                                finalMatrix = finalMatrix + Matrix4.Mult(Matrix4.Mult(sm1, sm2), envelope.BoneWeights[b]);
                            }
                        }
                        else
                        {
                            // If the vertex is not weighted then we use a 1:1 movement with the bone matrix.
                            finalMatrix = boneTransforms[indexFromDRW1];
                        }

                        // Multiply the data from the model file by the finalMatrix to put it in the correct (skinned) position
                        transformedPositions.Add(Vector3.Transform(shape.VertexData.Position[i], finalMatrix));

                        if (shape.VertexData.Normal.Count > 0)
                        {
                            Vector3 transformedNormal = Vector3.TransformNormal(shape.VertexData.Normal[i], finalMatrix);
                            transformedNormals.Add(transformedNormal);
                        }

                        //colorOverride.Add(isPartiallyWeighted ? WLinearColor.Black : WLinearColor.White);
                    }

                    // Re-upload to the GPU.
                    shape.OverrideVertPos = transformedPositions;
                    //shape.VertexData.Color0 = colorOverride;
                    if (transformedNormals.Count > 0)
                    {
                        shape.OverrideNormals = transformedNormals;
                    }
                    shape.UploadBuffersToGPU(true);
                }

                m_skinningInvalid = false;
            }

            //if (WInput.GetKeyDown(System.Windows.Input.Key.O))
            //    m_shapeIndex--;
            //if (WInput.GetKeyUp(System.Windows.Input.Key.P))
            //    m_shapeIndex++;

            m_shapeIndex = WMath.Clamp(m_shapeIndex, 0, SHP1Tag.ShapeCount - 1);

            RenderMeshRecursive(INF1Tag.HierarchyRoot);

            // We're going to restore some semblance of state after rendering ourselves, as models often modify weird and arbitrary GX values.
            GL.Enable(EnableCap.Blend);
            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
            GL.Enable(EnableCap.CullFace);
            GL.CullFace(CullFaceMode.Back);
            GL.Enable(EnableCap.DepthTest);
            GL.DepthMask(true);
            GL.Enable(EnableCap.Dither);
        }
Example #10
0
        public static ushort[] CreateTerrain(int chunkx, int chunky, bool save = false, bool erase = false)
        {
            ushort[] blocks = new ushort[Chunk.Width * Chunk.Height * Chunk.Depth];

            string id;
            ushort cacheindex = 0;
            Dictionary <string, ushort> idscache = new Dictionary <string, ushort>();

            for (int z = 0; z < Chunk.Depth; z++)
            {
                for (int y = 0; y < Chunk.Height; y++)
                {
                    for (int x = 0; x < Chunk.Width; x++)
                    {
                        id = "winecrash:air";

                        const float scale         = 0.025F;
                        const float contScale     = 0.001F;
                        const float mountainScale = 0.005F;
                        const float shiftX        = 0; //Début des farlands : 16000000 | Grosses Farlands : 200000000
                        const float shiftZ        = 0; //todo: auré tu fais chier avec tes commentaires.

                        const float caveScale = 0.1F;
                        const float thresold  = 0.3F;


                        float xsample = (chunkx * Chunk.Width + shiftX + x);
                        float ysample = (chunky * Chunk.Depth + shiftZ + z);

                        float  continentValue    = continents.GetValue(xsample * contScale, ysample * contScale);
                        double continentalHeight = WMath.Remap(WMath.Clamp(Math.Exp(continentValue), 0.0, 65.0), -1.0D, 1.0D, 55.0D, 63.0D);

                        float  landValue  = details.GetValue(xsample * scale, ysample * scale);
                        double landHeight = WMath.Remap(landValue, -1.0D, 1.0D, 0.0D, 30.0D);

                        float mountainValue = (float)WMath.Remap(mountainMult.GetValue(xsample * mountainScale, ysample * mountainScale), -1.0, 1.0, 0.0, 1.0);
                        mountainValue = (float)WMath.Clamp(Math.Pow(mountainValue, 4.0), 0.0, 1.0);

                        double final = continentalHeight + (landHeight * mountainValue);

                        int height = (int)final;

                        bool waterlevel = height < 64;


                        if (y == height)
                        {
                            if (waterlevel)
                            {
                                id = "winecrash:sand"; //sand
                            }
                            else
                            {
                                id = "winecrash:grass"; //grass
                            }
                        }
                        else if (y < height)
                        {
                            if (y > height - 3)
                            {
                                if (waterlevel)
                                {
                                    id = "winecrash:sand"; //sand
                                }
                                else
                                {
                                    id = "winecrash:dirt"; //dirt
                                }
                            }
                            else
                            {
                                id = "winecrash:stone";
                            }
                        }

                        /*if(isCave)
                         * {
                         *  id = "winecrash:air";
                         * }*/

                        if (y == 2)
                        {
                            if (World.WorldRandom.NextDouble() < 0.33D)
                            {
                                id = "winecrash:bedrock";
                            }
                        }
                        else if (y == 1)
                        {
                            if (World.WorldRandom.NextDouble() < 0.66D)
                            {
                                id = "winecrash:bedrock";
                            }
                        }
                        else if (y == 0)
                        {
                            id = "winecrash:bedrock";
                        }

                        if (!idscache.TryGetValue(id, out cacheindex))
                        {
                            cacheindex = ItemCache.GetIndex(id);
                            idscache.Add(id, cacheindex);
                        }
                        //Server.Log(id);
                        blocks[x + Chunk.Width * y + Chunk.Width * Chunk.Height * z] = cacheindex;//new Block(id);
                    }
                }
            }

            if (save)
            {
                string fileName = "save/" + $"c{chunkx}_{chunky}.json";

                if (erase)
                {
                    File.WriteAllText(fileName, ToJSON(blocks));
                }

                else if (!File.Exists(fileName))
                {
                    File.WriteAllText(fileName, ToJSON(blocks));
                }
            }

            return(blocks);
        }
Example #11
0
        protected override void Update()
        {
            if (Input.IsPressing(Keys.End))
            {
                FreeCTRL = !FreeCTRL;
            }

            if (!FreeCTRL)
            {
                return;
            }

            double newSpeed = Input.MouseScrollDelta * MoveScrollSensivity * Time.DeltaTime;

            this.MoveSpeed += newSpeed + MoveSpeed * Input.MouseScrollDelta * 0.2D;

            this.MoveSpeed = WMath.Clamp(this.MoveSpeed, 0.01D, double.PositiveInfinity);
            //if(Input.IsPressed(Keys.Mouse))
            //Debug.Log(this.WObject.Position);

            /*Vector2D deltas = Input.MouseDelta;
             *
             * double ax = (Angles.X + (deltas.X * Input.MouseSensivity * (float)Time.DeltaTime)) % 360.0F;
             * double ay = WMath.Clamp((Angles.Y + (deltas.Y * Input.MouseSensivity * (float)Time.DeltaTime)), -90.0F, 90.0F);
             *
             * Angles = new Vector2D(ax, ay);
             *
             * this.WObject.Rotation = new Quaternion(-ay, ax, 0.0F);*/

            Vector3D fwd  = this.WObject.Forward;
            Vector3D rght = this.WObject.Right;
            Vector3D up   = this.WObject.Up;

            Vector3D pos = this.WObject.Position;

            if (Input.IsPressed(Keys.Z))
            {
                fwd *= MoveSpeed * Time.DeltaTime;
            }
            else if (Input.IsPressed(Keys.S))
            {
                fwd *= -MoveSpeed * Time.DeltaTime;
            }
            else
            {
                fwd *= 0.0D;
            }

            if (Input.IsPressed(Keys.Q))
            {
                rght *= -MoveSpeed * Time.DeltaTime;
            }
            else if (Input.IsPressed(Keys.D))
            {
                rght *= MoveSpeed * Time.DeltaTime;
            }
            else
            {
                rght *= 0.0D;
            }

            if (Input.IsPressed(Keys.Space))
            {
                up *= MoveSpeed * Time.DeltaTime;
            }
            else if (Input.IsPressed(Keys.LeftShift))
            {
                up *= -MoveSpeed * Time.DeltaTime;
            }
            else
            {
                up *= 0.0D;
            }

            Player.Instance.WObject.Position += fwd - rght + up;


            if (Input.IsPressed(Keys.F3) && Input.IsPressing(Keys.A))
            {
                Debug.Log("Reconstructing");
                Debug.Log(Chunk.Chunks.Count);
                foreach (Chunk chunk in Chunk.Chunks)
                {
                    Task.Run(chunk.Construct);
                }
            }

            if (Input.IsPressing(Keys.K))
            {
                //Player.Instance.WObject.Position = new Vector3F(140_000_000F, 128F, 0.0F);
                Player.Instance.ForceInvokeChunkChange();
            }
        }
        public Sweep SweepCollide(Chunk c, BoxCollider b)
        {
            //force = Vector3D.Zero;
            //translation = Vector3D.Zero;

            RigidBody rb = b.WObject.GetModule <RigidBody>();

            Vector3D bc = b.Center;
            Vector3D be = b.Extents * 4;


            Vector3D cc = c.WObject.Position +
                          Vector3D.Up * Chunk.Height / 2.0D +
                          Vector3D.Right * Chunk.Width / 2.0D +
                          Vector3D.Forward * Chunk.Depth / 2.0D;
            Vector3D ce = Vector3D.One * new Vector3D(Chunk.Width, Chunk.Height, Chunk.Depth) / 2.0D;

            // if outside of chunk, no collision.
            if (                             //Y
                cc.Y - ce.Y > bc.Y + be.Y || // if too low
                cc.Y + ce.Y < bc.Y - be.Y || // if too high

                //X
                cc.X - ce.X > bc.X + be.X || // if too much left
                cc.X + ce.X < bc.X - be.X || // if too much right

                //Z
                cc.Z - ce.Z > bc.Z + be.Z || // if too much behind
                cc.Z + ce.Z < bc.Z - be.Z    // if too much forward
                )
            {
                return(new Sweep());
            }
            else // the box collider is within the chunk
            {
                // max coords

                Vector3D max = bc + be;
                Vector3D min = bc - be;

                Vector3D cmax = new Vector3D(
                    WMath.Clamp(max.X, c.Coordinates.X * Chunk.Width,
                                c.Coordinates.X * Chunk.Width + (Chunk.Width - 1)),
                    WMath.Clamp(max.Y, 0, 255),
                    WMath.Clamp(max.Z, c.Coordinates.Y * Chunk.Depth, c.Coordinates.Y * Chunk.Depth + (Chunk.Depth - 1))
                    );

                Vector3D cmin = new Vector3D(
                    WMath.Clamp(min.X, c.Coordinates.X * Chunk.Width,
                                c.Coordinates.X * Chunk.Width + (Chunk.Width - 1)),
                    WMath.Clamp(min.Y, 0, 255),
                    WMath.Clamp(min.Z, c.Coordinates.Y * Chunk.Depth, c.Coordinates.Y * Chunk.Depth + (Chunk.Depth - 1))
                    );

                World.GlobalToLocal(cmax, out _, out Vector3I maxBpos);
                World.GlobalToLocal(cmin, out _, out Vector3I minBpos);


                List <AABBCollider> colliders = new List <AABBCollider>();

                for (int z = minBpos.Z; z <= maxBpos.Z; z++)
                {
                    for (int y = minBpos.Y; y <= maxBpos.Y; y++)
                    {
                        for (int x = minBpos.X; x <= maxBpos.X; x++)
                        {
                            if (c[x, y, z].Collides)
                            {
                                Vector3D blockExtents = new Vector3D(0.5D);
                                Vector3D blockCenter  = new Vector3D(x + c.Coordinates.X * Chunk.Width, y,
                                                                     z + c.Coordinates.Y * Chunk.Depth) + blockExtents;

                                FreeBoxCollider collider = new FreeBoxCollider()
                                {
                                    Center  = blockCenter,
                                    Extents = blockExtents
                                };

                                colliders.Add(collider);
                            }
                        }
                    }
                }

                Sweep resultingSweep =
                    new BoxBoxCollisionProvider().SweepCollideInto(b, rb.Velocity * Time.PhysicsDelta,
                                                                   colliders.ToArray());

                for (int i = 0; i < colliders.Count; i++)
                {
                    colliders[i].Delete();
                }

                colliders.Clear();
                colliders = null;

                return(resultingSweep);
            }
        }