Пример #1
0
 public void SetBlock(Vector3 position, Block value)
 {
     position = position.Floor();
     Vector3 relativePosition = position;
     position.X = (int)(position.X) / Chunk.Width;
     position.Y = 0;
     position.Z = (int)(position.Z) / Chunk.Depth;
     
     relativePosition.X = (int)(relativePosition.X) % Chunk.Width;
     relativePosition.Z = (int)(relativePosition.Z) % Chunk.Depth;
     
     if (!Chunks.ContainsKey(position))
         Chunks.Add(position, WorldGenerator.GenerateChunk(position, this));
     
     Chunks[position].SetBlock(relativePosition, value);
 }
        private static void GenerateCurvedIllusionPlaneVertexData(HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float cameraPosition, float sphereRadius, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength)
        {
            Vector3 vec;
            Vector3 norm;
            float sphereDistance;
            unsafe {
                // lock the vertex buffer
                IntPtr data = vertexBuffer.Lock(BufferLocking.Discard);

                float* pData = (float*)data.ToPointer();

                for (int y = 0; y < ySegments + 1; ++y) {
                    for (int x = 0; x < xSegments + 1; ++x) {
                        // centered on origin
                        vec.x = (x * xSpace) - halfWidth;
                        vec.y = (y * ySpace) - halfHeight;
                        vec.z = 0.0f;

                        // transform by orientation and distance
                        vec = xform * vec;

                        // assign to geometry
                        *pData++ = vec.x;
                        *pData++ = vec.y;
                        *pData++ = vec.z;

                        // build bounds as we go
                        if (firstTime) {
                            min = vec;
                            max = vec;
                            maxSquaredLength = vec.LengthSquared;
                            firstTime = false;
                        } else {
                            min.Floor(vec);
                            max.Ceil(vec);
                            maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared);
                        }

                        if (normals) {
                            norm = Vector3.UnitZ;
                            norm = orientation * norm;

                            *pData++ = vec.x;
                            *pData++ = vec.y;
                            *pData++ = vec.z;
                        }

                        // generate texture coordinates, normalize position, modify by orientation to return +y up
                        vec = orientation.Inverse() * vec;
                        vec.Normalize();

                        // find distance to sphere
                        sphereDistance = MathUtil.Sqrt(cameraPosition * cameraPosition * (vec.y * vec.y - 1.0f) + sphereRadius * sphereRadius) - cameraPosition * vec.y;

                        vec.x *= sphereDistance;
                        vec.z *= sphereDistance;

                        // use x and y on sphere as texture coordinates, tiled
                        float s = vec.x * (0.01f * uTiles);
                        float t = vec.z * (0.01f * vTiles);
                        for (int i = 0; i < numberOfTexCoordSets; i++) {
                            *pData++ = s;
                            *pData++ = (1 - t);
                        }
                    } // x
                } // y

                // unlock the buffer
                vertexBuffer.Unlock();
            } // unsafe
        }
Пример #3
0
		public override void NotifyCurrentCamera( Camera cam )
		{
			if ( this.mForcedRenderLevel >= 0 )
			{
				this.mRenderLevel = this.mForcedRenderLevel;
				return;
			}


			var cpos = cam.DerivedPosition;
			var aabb = GetWorldBoundingBox( true );
			var diff = new Vector3( 0, 0, 0 );
			diff.Floor( cpos - aabb.Minimum );
			diff.Ceil( cpos - aabb.Maximum );

			var L = diff.LengthSquared;

			this.mRenderLevel = -1;

			for ( var i = 0; i < this.mOptions.maxGeoMipMapLevel; i++ )
			{
				if ( this.mMinLevelDistSqr[ i ] > L )
				{
					this.mRenderLevel = i - 1;
					break;
				}
			}

			if ( this.mRenderLevel < 0 )
			{
				this.mRenderLevel = this.mOptions.maxGeoMipMapLevel - 1;
			}

			if ( this.mOptions.lodMorph )
			{
				// Get the next LOD level down
				var nextLevel = this.mNextLevelDown[ this.mRenderLevel ];
				if ( nextLevel == 0 )
				{
					// No next level, so never morph
					this.mLODMorphFactor = 0;
				}
				else
				{
					// Set the morph such that the morph happens in the last 0.25 of
					// the distance range
					var range = this.mMinLevelDistSqr[ nextLevel ] - this.mMinLevelDistSqr[ this.mRenderLevel ];
					if ( range > 0 )
					{
						var percent = ( L - this.mMinLevelDistSqr[ this.mRenderLevel ] )/range;
						// scale result so that msLODMorphStart == 0, 1 == 1, clamp to 0 below that
						var rescale = 1.0f/( 1.0f - this.mOptions.lodMorphStart );
						this.mLODMorphFactor = Math.Max( ( percent - this.mOptions.lodMorphStart )*rescale, 0.0 );
					}
					else
					{
						// Identical ranges
						this.mLODMorphFactor = 0.0f;
					}

					//assert(mLODMorphFactor >= 0 && mLODMorphFactor <= 1);
				}

				// Bind the correct delta buffer if it has changed
				// nextLevel - 1 since the first entry is for LOD 1 (since LOD 0 never needs it)
				if ( this.mLastNextLevel != nextLevel )
				{
					if ( nextLevel > 0 )
					{
						this.mTerrain.vertexBufferBinding.SetBinding( (short)DELTA_BINDING, this.mDeltaBuffers[ nextLevel - 1 ] );
					}
					else
					{
						// bind dummy (incase bindings checked)
						this.mTerrain.vertexBufferBinding.SetBinding( (short)DELTA_BINDING, this.mDeltaBuffers[ 0 ] );
					}
				}
				this.mLastNextLevel = nextLevel;
			}
		}
Пример #4
0
        public override void Update(IUpdateArgs args)
        {
            if (WaitingOnChunk && Age % 4 == 0)
            {
                NoAi = true;

                if (Level.GetChunk(KnownPosition.GetCoordinates3D(), true) != null)
                {
                    Velocity       = Vector3.Zero;
                    WaitingOnChunk = false;
                    NoAi           = false;
                }
            }

            ChunkCoordinates oldChunkCoordinates = new ChunkCoordinates(base.KnownPosition);
            bool             sprint = IsSprinting;
            bool             sneak  = IsSneaking;

            if (!CanFly && IsFlying)
            {
                IsFlying = false;
            }

            Controller.Update(args.GameTime);
            //KnownPosition.HeadYaw = KnownPosition.Yaw;

            if (IsSprinting && !sprint)
            {
                FOVModifier = 10;

                Network.EntityAction((int)EntityId, EntityAction.StartSprinting);
            }
            else if (!IsSprinting && sprint)
            {
                FOVModifier = 0;

                Network.EntityAction((int)EntityId, EntityAction.StopSprinting);
            }

            if (IsSneaking != sneak)
            {
                if (IsSneaking)
                {
                    Network.EntityAction((int)EntityId, EntityAction.StartSneaking);
                    Camera.UpdateOffset(new Vector3(0f, -0.15f, 0.35f));
                }
                else
                {
                    Network.EntityAction((int)EntityId, EntityAction.StopSneaking);
                    Camera.UpdateOffset(Vector3.Zero);
                }
            }

            var previousCheckedInput = _prevCheckedInput;

            if ((Controller.CheckInput && Controller.CheckMovementInput))
            {
                _prevCheckedInput = true;
                if (!previousCheckedInput || World.FormManager.IsShowingForm)
                {
                    return;
                }

                UpdateRayTracer();

                //if (Controller.InputManager.IsDown(InputCommand.LeftClick) && DateTime.UtcNow - _lastAnimate >= TimeSpan.FromMilliseconds(500))
                //{
                //	SwingArm(true);
                //}

                var hitEntity = HitEntity;
                if (hitEntity != null && Controller.InputManager.IsPressed(InputCommand.LeftClick))
                {
                    if (_destroyingBlock)
                    {
                        StopBreakingBlock(forceCanceled: true);
                    }

                    InteractWithEntity(hitEntity, true);
                }
                else if (hitEntity != null && Controller.InputManager.IsPressed(InputCommand.RightClick))
                {
                    if (_destroyingBlock)
                    {
                        StopBreakingBlock(forceCanceled: true);
                    }

                    InteractWithEntity(hitEntity, false);
                }
                else if (hitEntity == null && !_destroyingBlock &&
                         Controller.InputManager.IsPressed(InputCommand.LeftClick) &&
                         !HasRaytraceResult)
                {
                    SwingArm(true);
                }
                else if (hitEntity == null && !_destroyingBlock && Controller.InputManager.IsDown(InputCommand.LeftClick) && !IsWorldImmutable && HasRaytraceResult)                 //Destroying block.
                {
                    StartBreakingBlock();
                }
                else if (_destroyingBlock && Controller.InputManager.IsUp(InputCommand.LeftClick))
                {
                    StopBreakingBlock();
                }
                else if (_destroyingBlock && Controller.InputManager.IsDown(InputCommand.LeftClick))
                {
                    if (_destroyingTarget != new BlockCoordinates(Vector3.Floor(Raytraced)))
                    {
                        StopBreakingBlock(true, true);

                        if (Gamemode != Gamemode.Creative)
                        {
                            StartBreakingBlock();
                        }
                    }
                    else
                    {
                        if ((DateTime.UtcNow - _lastAnimate).TotalMilliseconds > 500)
                        {
                            _lastAnimate = DateTime.UtcNow;
                            SwingArm(true);
                        }

                        var timeRan = (DateTime.UtcNow - _destroyingTick).TotalMilliseconds / 50d;
                        if (timeRan >= _destroyTimeNeeded)
                        {
                            StopBreakingBlock(true);
                        }
                    }
                }
                else if (Controller.InputManager.IsPressed(InputCommand.RightClick))
                {
                    bool handledClick = false;
                    var  item         = Inventory[Inventory.SelectedSlot];
                    // Log.Debug($"Right click!");
                    if (item != null)
                    {
                        handledClick = HandleRightClick(item, Inventory.SelectedSlot);
                    }

                    /*if (!handledClick && Inventory.OffHand != null && !(Inventory.OffHand is ItemAir))
                     * {
                     *      handledClick = HandleRightClick(Inventory.OffHand, 1);
                     * }*/
                }

                if (hitEntity != null && HasCollision)
                {
                    if (IsColliding(hitEntity))
                    {
                        //var distance = DistanceToHorizontal(hitEntity);
                        //	Velocity += (KnownPosition.ToVector3() - hitEntity.KnownPosition.ToVector3());
                    }
                }
            }
            else
            {
                if (_destroyingBlock)
                {
                    StopBreakingBlock();
                }

                _prevCheckedInput     = false;
                _lastTimeWithoutInput = DateTime.UtcNow;
            }

            if (PreviousSlot != Inventory.SelectedSlot)
            {
                var slot = Inventory.SelectedSlot;
                Network?.HeldItemChanged(Inventory[Inventory.SelectedSlot], (short)slot);
                PreviousSlot = slot;
            }

            base.Update(args);
        }
Пример #5
0
 public static Vector3 Floor(this Vector3 vector)
 {
     return(vector.Floor(Axes.XYZW));
 }
        private static void GenerateCurvedIllusionPlaneVertexData(HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float cameraPosition, float sphereRadius, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength)
        {
            Vector3 vec;
            Vector3 norm;
            float   sphereDistance;

            unsafe {
                // lock the vertex buffer
                IntPtr data = vertexBuffer.Lock(BufferLocking.Discard);

                float *pData = (float *)data.ToPointer();

                for (int y = 0; y < ySegments + 1; ++y)
                {
                    for (int x = 0; x < xSegments + 1; ++x)
                    {
                        // centered on origin
                        vec.x = (x * xSpace) - halfWidth;
                        vec.y = (y * ySpace) - halfHeight;
                        vec.z = 0.0f;

                        // transform by orientation and distance
                        vec = xform * vec;

                        // assign to geometry
                        *pData++ = vec.x;
                        *pData++ = vec.y;
                        *pData++ = vec.z;

                        // build bounds as we go
                        if (firstTime)
                        {
                            min = vec;
                            max = vec;
                            maxSquaredLength = vec.LengthSquared;
                            firstTime        = false;
                        }
                        else
                        {
                            min.Floor(vec);
                            max.Ceil(vec);
                            maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared);
                        }

                        if (normals)
                        {
                            norm = Vector3.UnitZ;
                            norm = orientation * norm;

                            *pData++ = vec.x;
                            *pData++ = vec.y;
                            *pData++ = vec.z;
                        }

                        // generate texture coordinates, normalize position, modify by orientation to return +y up
                        vec = orientation.Inverse() * vec;
                        vec.Normalize();

                        // find distance to sphere
                        sphereDistance = MathUtil.Sqrt(cameraPosition * cameraPosition * (vec.y * vec.y - 1.0f) + sphereRadius * sphereRadius) - cameraPosition * vec.y;

                        vec.x *= sphereDistance;
                        vec.z *= sphereDistance;

                        // use x and y on sphere as texture coordinates, tiled
                        float s = vec.x * (0.01f * uTiles);
                        float t = vec.z * (0.01f * vTiles);
                        for (int i = 0; i < numberOfTexCoordSets; i++)
                        {
                            *pData++ = s;
                            *pData++ = (1 - t);
                        }
                    } // x
                }     // y

                // unlock the buffer
                vertexBuffer.Unlock();
            } // unsafe
        }
Пример #7
0
		private void _generateCurvedIllusionPlaneVertexData( HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float curvature, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength )
		{
			// Imagine a large sphere with the camera located near the top
			// The lower the curvature, the larger the sphere
			// Use the angle from viewer to the points on the plane
			// Credit to Aftershock for the general approach
			Real cameraPosition;      // Camera position relative to sphere center

			// Derive sphere radius
			//Vector3 vertPos;  // position relative to camera
			//Real sphDist;      // Distance from camera to sphere along box vertex vector
			// Vector3 camToSph; // camera position to sphere
			Real sphereRadius;// Sphere radius
			// Actual values irrelevant, it's the relation between sphere radius and camera position that's important
			Real sphRadius = 100.0f;
			Real camDistance = 5.0f;

			sphereRadius = sphRadius - curvature;
			cameraPosition = sphereRadius - camDistance;

			Vector3 vec;
			Vector3 norm;
			float sphereDistance;
			unsafe
			{
				// lock the vertex buffer
				IntPtr data = vertexBuffer.Lock( BufferLocking.Discard );

				float* pData = (float*)data.ToPointer();

				for ( int y = 0; y < ySegments + 1; ++y )
				{
					for ( int x = 0; x < xSegments + 1; ++x )
					{
						// centered on origin
						vec.x = ( x * xSpace ) - halfWidth;
						vec.y = ( y * ySpace ) - halfHeight;
						vec.z = 0.0f;

						// transform by orientation and distance
						vec = xform * vec;

						// assign to geometry
						*pData++ = vec.x;
						*pData++ = vec.y;
						*pData++ = vec.z;

						// build bounds as we go
						if ( firstTime )
						{
							min = vec;
							max = vec;
							maxSquaredLength = vec.LengthSquared;
							firstTime = false;
						}
						else
						{
							min.Floor( vec );
							max.Ceil( vec );
							maxSquaredLength = Utility.Max( maxSquaredLength, vec.LengthSquared );
						}

						if ( normals )
						{
							norm = Vector3.UnitZ;
							norm = orientation * norm;

							*pData++ = vec.x;
							*pData++ = vec.y;
							*pData++ = vec.z;
						}

						// generate texture coordinates, normalize position, modify by orientation to return +y up
						vec = orientation.Inverse() * vec;
						vec.Normalize();

						// find distance to sphere
						sphereDistance = Utility.Sqrt( cameraPosition * cameraPosition * ( vec.y * vec.y - 1.0f ) + sphereRadius * sphereRadius ) - cameraPosition * vec.y;

						vec.x *= sphereDistance;
						vec.z *= sphereDistance;

						// use x and y on sphere as texture coordinates, tiled
						float s = vec.x * ( 0.01f * uTiles );
						float t = vec.z * ( 0.01f * vTiles );
						for ( int i = 0; i < numberOfTexCoordSets; i++ )
						{
							*pData++ = s;
							*pData++ = ( 1 - t );
						}
					} // x
				} // y

				// unlock the buffer
				vertexBuffer.Unlock();
			} // unsafe
		}
Пример #8
0
		private void _generatePlaneVertexData( HardwareVertexBuffer vbuf, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 transform, bool firstTime, bool normals, Matrix4 rotation, int numTexCoordSets, float xTexCoord, float yTexCoord, SubMesh subMesh, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength )
		{
			Vector3 vec;
			unsafe
			{
				// lock the vertex buffer
				IntPtr data = vbuf.Lock( BufferLocking.Discard );

				float* pData = (float*)data.ToPointer();

				for ( int y = 0; y <= ySegments; y++ )
				{
					for ( int x = 0; x <= xSegments; x++ )
					{
						// centered on origin
						vec.x = ( x * xSpace ) - halfWidth;
						vec.y = ( y * ySpace ) - halfHeight;
						vec.z = 0.0f;

						vec = transform.TransformAffine( vec );

						*pData++ = vec.x;
						*pData++ = vec.y;
						*pData++ = vec.z;

						// Build bounds as we go
						if ( firstTime )
						{
							min = vec;
							max = vec;
							maxSquaredLength = vec.LengthSquared;
							firstTime = false;
						}
						else
						{
							min.Floor( vec );
							max.Ceil( vec );
							maxSquaredLength = Utility.Max( maxSquaredLength, vec.LengthSquared );
						}

						if ( normals )
						{
							vec = Vector3.UnitZ;
							vec = rotation.TransformAffine( vec );

							*pData++ = vec.x;
							*pData++ = vec.y;
							*pData++ = vec.z;
						}

						for ( int i = 0; i < numTexCoordSets; i++ )
						{
							*pData++ = x * xTexCoord;
							*pData++ = 1 - ( y * yTexCoord );
						} // for texCoords
					} // for x
				} // for y

				// unlock the buffer
				vbuf.Unlock();

				subMesh.useSharedVertices = true;

			} // unsafe
		}
Пример #9
0
        private void InitDebugInfo()
        {
            string gameVersion = VersionUtils.GetVersion();

            _debugInfo.AddDebugLeft(
                () =>
            {
                double avg = 0;

                /*	if (World.ChunkManager.TotalChunkUpdates > 0)
                 *      {
                 *              avg = (World.ChunkManager.ChunkUpdateTime / World.ChunkManager.TotalChunkUpdates)
                 *                 .TotalMilliseconds;
                 *      }*/

                return
                ($"Alex {gameVersion} ({Alex.FpsMonitor.Value:##} FPS, {World.Ticker.TicksPerSecond:##} TPS, Chunk Updates: {World.EnqueuedChunkUpdates} queued, {World.ConcurrentChunkUpdates} active)");
            }, TimeSpan.FromMilliseconds(50));

            _debugInfo.AddDebugLeft(() =>
            {
                var pos      = World.Player.KnownPosition;
                var blockPos = pos.GetCoordinates3D();
                return($"Position: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}, OnGround={pos.OnGround}) / Block: ({blockPos.X:D}, {blockPos.Y:D}, {blockPos.Z:D})");
            });

            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.KnownPosition;
                return($"Facing: {GetCardinalDirection(pos)} (HeadYaw={pos.HeadYaw:F2}, Yaw={pos.Yaw:F2}, Pitch={pos.Pitch:F2})");
            });

            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.Velocity;
                return($"Velocity: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) ({World.Player.CurrentSpeed:F3} m/s)");               // / Target Speed: {(World.Player.CalculateMovementSpeed() * 20f):F3} m/s";
            });
            _debugInfo.AddDebugLeft(() => $"Vertices: {World.Vertices:N0} ({GetBytesReadable((long)(World.Vertices * BlockShaderVertex.VertexDeclaration.VertexStride))})", TimeSpan.FromMilliseconds(500));
            //	_debugInfo.AddDebugLeft(() => $"IndexBuffer Elements: {World.IndexBufferSize:N0} ({GetBytesReadable(World.IndexBufferSize * 4)})");
            _debugInfo.AddDebugLeft(() => $"Chunks: {World.ChunkCount}, {World.ChunkManager.RenderedChunks}", TimeSpan.FromMilliseconds(500));
            _debugInfo.AddDebugLeft(() => $"Entities: {World.EntityManager.EntityCount}, {World.EntityManager.EntitiesRendered}", TimeSpan.FromMilliseconds(500));
            _debugInfo.AddDebugLeft(() =>
            {
                return($"Biome: {_currentBiome.Name} ({_currentBiomeId})");
            }, TimeSpan.FromMilliseconds(500));
            //_debugInfo.AddDebugLeft(() => { return $"Do DaylightCycle: {World.DoDaylightcycle}"; });

            _debugInfo.AddDebugRight(Alex.OperatingSystem);
            _debugInfo.AddDebugRight(Alex.Gpu);
            _debugInfo.AddDebugRight($"{Alex.DotnetRuntime}\n");
            _debugInfo.AddDebugRight(Alex.RenderingEngine);
            //_debugInfo.AddDebugRight(() => MemoryUsageDisplay);
            _debugInfo.AddDebugRight(() => $"RAM: {GetBytesReadable(_ramUsage, 2)}", TimeSpan.FromMilliseconds(1000));
            _debugInfo.AddDebugRight(() => $"GPU: {GetBytesReadable(GpuResourceManager.GetMemoryUsage, 2)}", TimeSpan.FromMilliseconds(1000));
            _debugInfo.AddDebugRight(() =>
            {
                return
                ($"Threads: {(_threadsUsed):00}/{_maxThreads}");
            }, TimeSpan.FromMilliseconds(50));
            _debugInfo.AddDebugRight(() =>
            {
                var player = World?.Player;

                if (player == null)
                {
                    return("");
                }

                if (player.HasRaytraceResult)
                {
                    var raytracedBlock = player.RaytracedBlock;
                    var adjacentBlock  = player.AdjacentRaytraceBlock;
                    var adj            = Vector3.Floor(adjacentBlock) - Vector3.Floor(raytracedBlock);
                    adj.Normalize();

                    var face = adj.GetBlockFace();

                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine($"Target: {raytracedBlock} Face: {face}");
                    sb.AppendLine(
                        $"Skylight: {World.GetSkyLight(raytracedBlock)} Face Skylight: {World.GetSkyLight(adjacentBlock)}");
                    sb.AppendLine(
                        $"Blocklight: {World.GetBlockLight(raytracedBlock)} Face Blocklight: {World.GetBlockLight(adjacentBlock)}");

                    //sb.AppendLine($"Skylight scheduled: {World.IsScheduled((int) _raytracedBlock.X, (int) _raytracedBlock.Y, (int) _raytracedBlock.Z)}");

                    foreach (var bs in World
                             .GetBlockStates((int)raytracedBlock.X, (int)raytracedBlock.Y, (int)raytracedBlock.Z))
                    {
                        var blockstate = bs.State;
                        if (blockstate != null && blockstate.Block.HasHitbox)
                        {
                            sb.AppendLine($"{blockstate.Name} (S: {bs.Storage})");

                            /*if (blockstate.IsMultiPart)
                             * {
                             *      sb.AppendLine($"MultiPart=true");
                             *      sb.AppendLine();
                             *
                             *      sb.AppendLine("Models:");
                             *
                             *      foreach (var model in blockstate.AppliedModels)
                             *      {
                             *              sb.AppendLine(model);
                             *      }
                             * }*/

                            var dict = blockstate.ToDictionary();

                            if (dict.Count > 0)
                            {
                                sb.AppendLine();
                                sb.AppendLine("Blockstate:");

                                foreach (var kv in dict)
                                {
                                    sb.AppendLine($"{kv.Key}={kv.Value}");
                                }
                            }
                        }
                    }

                    return(sb.ToString());
                }
                else
                {
                    return(string.Empty);
                }
            }, TimeSpan.FromMilliseconds(500));

            _debugInfo.AddDebugRight(() =>
            {
                var player = World.Player;
                if (player == null || player.HitEntity == null)
                {
                    return(string.Empty);
                }

                var entity = player.HitEntity;
                return($"Hit entity: {entity.EntityId} / {entity.ToString()}");
            }, TimeSpan.FromMilliseconds(500));
        }
Пример #10
0
        private bool HandleClick(Item slot, int hand, bool canModifyWorld = true, bool isLeftClick = false)
        {
            SwingArm(true);
            //if (ItemFactory.ResolveItemName(slot.ItemID, out string itemName))
            {
                var flooredAdj      = Vector3.Floor(AdjacentRaytrace);
                var raytraceFloored = Vector3.Floor(Raytraced);

                var adj = flooredAdj - raytraceFloored;
                adj.Normalize();

                var face = adj.GetBlockFace();

                var remainder = new Vector3(AdjacentRaytrace.X - flooredAdj.X,
                                            AdjacentRaytrace.Y - flooredAdj.Y, AdjacentRaytrace.Z - flooredAdj.Z);

                var coordR = new BlockCoordinates(raytraceFloored);

                //IBlock block = null;
                if (!IsWorldImmutable && HasRaytraceResult)
                {
                    var  existingBlock = Level.GetBlock(coordR);
                    bool isBlockItem   = slot is ItemBlock;

                    if (existingBlock.CanInteract && (!isBlockItem || IsSneaking))
                    {
                        Network?.WorldInteraction(coordR, face, hand, remainder);

                        return(true);
                    }

                    if (slot is ItemBlock ib && canModifyWorld)
                    {
                        BlockState blockState = ib.Block;

                        if (blockState != null && !(blockState.Block is Air) && HasRaytraceResult)
                        {
                            if (existingBlock.IsReplacible || !existingBlock.Solid)
                            {
                                if (CanPlaceBlock(coordR, (Block)blockState.Block))
                                {
                                    Level.SetBlockState(coordR, blockState);

                                    Network?.BlockPlaced(coordR.BlockDown(), BlockFace.Up, hand, remainder, this);

                                    return(true);
                                }
                            }
                            else
                            {
                                var target = new BlockCoordinates(raytraceFloored + adj);
                                if (CanPlaceBlock(target, (Block)blockState.Block))
                                {
                                    Level.SetBlockState(target, blockState);

                                    Network?.BlockPlaced(coordR, face, hand, remainder, this);

                                    return(true);
                                }
                            }
                        }
                    }
                }

                if (!(slot is ItemAir) && slot.Id > 0 && slot.Count > 0)
                {
                    ItemUseAction action;
                    if (isLeftClick)
                    {
                        action = HasRaytraceResult ? ItemUseAction.ClickBlock : ItemUseAction.ClickAir;
                    }
                    else
                    {
                        action = HasRaytraceResult ? ItemUseAction.RightClickBlock : ItemUseAction.RightClickAir;
                    }

                    Network?.UseItem(slot, hand, action);
                    return(true);
                }
            }

            return(false);
        }
Пример #11
0
 public static Vector3 Frac(this Vector3 v) => v - v.Floor();
Пример #12
0
    private void SetHighlightBlockPos()
    {
        HighlightBlockPos = new Vector3Int(-1, -1, -1);

        Vector3      dir = cam.forward;
        List <float> ts  = new List <float>();

        float x = cam.position.x % 1;
        float y = cam.position.y % 1;
        float z = cam.position.z % 1;

        if (dir.x != 0)
        {
            for (float r = 1; r < Range; r++)
            {
                if (dir.x > 0)
                {
                    ts.Add((r - x) / dir.x + 0.01f);
                }
                else
                {
                    ts.Add((-r - x + 1) / dir.x + 0.01f);
                }
            }
        }
        if (dir.y != 0)
        {
            for (float r = 1; r < Range; r++)
            {
                if (dir.y > 0)
                {
                    ts.Add((r - y) / dir.y + 0.01f);
                }
                else
                {
                    ts.Add((-r - y + 1) / dir.y + 0.01f);
                }
            }
        }
        if (dir.z != 0)
        {
            for (float r = 1; r < Range; r++)
            {
                if (dir.z > 0)
                {
                    ts.Add((r - z) / dir.z + 0.01f);
                }
                else
                {
                    ts.Add((-r - z + 1) / dir.z + 0.01f);
                }
            }
        }

        ts.Sort();

        int t = 0;

        while (HighlightBlockPos.x < 0 && t < ts.Count && ts[t] < Range)
        {
            LookAtPoint = (dir * ts[t] + cam.position);
            Vector3Int block = LookAtPoint.Floor();
            if (world.GetBlockTypeAt(block) != 0)
            {
                HighlightBlockPos = block;
            }
            ++t;
        }

        HighlightBlock.position = HighlightBlockPos + new Vector3(0.5f, 0.5f, 0.5f);
    }
Пример #13
0
		protected virtual void _updateFrustum()
		{
			Real vpTop, vpRight, vpBottom, vpLeft;

			CalculateProjectionParameters( out vpLeft, out vpRight, out vpBottom, out vpTop );

			if ( !this._customProjectionMatrix )
			{
				// The code below will dealing with general projection
				// parameters, similar glFrustum and glOrtho.
				// Doesn't optimise manually except division operator, so the
				// code more self-explaining.

				Real inv_w = 1.0f/( vpRight - vpLeft );
				Real inv_h = 1.0f/( vpTop - vpBottom );
				Real inv_d = 1.0f/( this._farDistance - this._nearDistance );

				// Recalc if frustum params changed
				if ( this._projectionType == Projection.Perspective )
				{
					// Calc matrix elements
					Real A = 2.0f*this._nearDistance*inv_w;
					Real B = 2.0f*this._nearDistance*inv_h;
					Real C = ( vpRight + vpLeft )*inv_w;
					Real D = ( vpTop + vpBottom )*inv_h;
					Real q, qn;
					if ( this._farDistance == 0.0f )
					{
						// Infinite far plane
						q = Frustum.InfiniteFarPlaneAdjust - 1.0f;
						qn = this._nearDistance*( Frustum.InfiniteFarPlaneAdjust - 2.0f );
					}
					else
					{
						q = -( this._farDistance + this._nearDistance )*inv_d;
						qn = -2.0f*( this._farDistance*this._nearDistance )*inv_d;
					}

					// NB: This creates 'uniform' perspective projection matrix,
					// which depth range [-1,1], right-handed rules
					//
					// [ A   0   C   0  ]
					// [ 0   B   D   0  ]
					// [ 0   0   q   qn ]
					// [ 0   0   -1  0  ]
					//
					// A = 2 * near / (right - left)
					// B = 2 * near / (top - bottom)
					// C = (right + left) / (right - left)
					// D = (top + bottom) / (top - bottom)
					// q = - (far + near) / (far - near)
					// qn = - 2 * (far * near) / (far - near)

					this._projectionMatrix = Matrix4.Zero;
					this._projectionMatrix.m00 = A;
					this._projectionMatrix.m02 = C;
					this._projectionMatrix.m11 = B;
					this._projectionMatrix.m12 = D;
					this._projectionMatrix.m22 = q;
					this._projectionMatrix.m23 = qn;
					this._projectionMatrix.m32 = -1.0f;

					if ( this.useObliqueDepthProjection )
					{
						// Translate the plane into view space

						// Don't use getViewMatrix here, incase overrided by
						// camera and return a cull frustum view matrix
						UpdateView();

						var plane = this._viewMatrix*this.obliqueProjPlane;

						// Thanks to Eric Lenyel for posting this calculation
						// at www.terathon.com

						// Calculate the clip-space corner point opposite the
						// clipping plane
						// as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
						// transform it into camera space by multiplying it
						// by the inverse of the projection matrix

						/* generalised version
                        Vector4 q = matrix.inverse() *
                        Vector4(Math::Sign(plane.normal.x),
                        Math::Sign(plane.normal.y), 1.0f, 1.0f);
                         */
						var q1 = new Vector4();
						q1.x = ( System.Math.Sign( plane.Normal.x ) + this._projectionMatrix.m02 )/this._projectionMatrix.m00;
						q1.y = ( System.Math.Sign( plane.Normal.y ) + this._projectionMatrix.m12 )/this._projectionMatrix.m11;
						q1.z = -1.0f;
						q1.w = ( 1.0f + this._projectionMatrix.m22 )/this._projectionMatrix.m23;

						// Calculate the scaled plane vector
						var clipPlane4d = new Vector4( plane.Normal.x, plane.Normal.y, plane.Normal.z, plane.D );
						var c = clipPlane4d*( 2.0f/( clipPlane4d.Dot( q1 ) ) );

						// Replace the third row of the projection matrix
						this._projectionMatrix.m20 = c.x;
						this._projectionMatrix.m21 = c.y;
						this._projectionMatrix.m22 = c.z + 1.0f;
						this._projectionMatrix.m23 = c.w;
					}
				} // perspective
				else if ( this._projectionType == Projection.Orthographic )
				{
					var A = 2.0f*inv_w;
					var B = 2.0f*inv_h;
					Real C = -( vpRight + vpLeft )*inv_w;
					Real D = -( vpTop + vpBottom )*inv_h;
					Real q, qn;
					if ( this._farDistance == 0.0f )
					{
						// Can not do infinite far plane here, avoid divided zero only
						q = -Frustum.InfiniteFarPlaneAdjust/this._nearDistance;
						qn = -Frustum.InfiniteFarPlaneAdjust - 1.0f;
					}
					else
					{
						q = -2.0f*inv_d;
						qn = -( this._farDistance + this._nearDistance )*inv_d;
					}

					// NB: This creates 'uniform' orthographic projection matrix,
					// which depth range [-1,1], right-handed rules
					//
					// [ A   0   0   C  ]
					// [ 0   B   0   D  ]
					// [ 0   0   q   qn ]
					// [ 0   0   0   1  ]
					//
					// A = 2 * / (right - left)
					// B = 2 * / (top - bottom)
					// C = - (right + left) / (right - left)
					// D = - (top + bottom) / (top - bottom)
					// q = - 2 / (far - near)
					// qn = - (far + near) / (far - near)

					this._projectionMatrix = Matrix4.Zero;
					this._projectionMatrix.m00 = A;
					this._projectionMatrix.m03 = C;
					this._projectionMatrix.m11 = B;
					this._projectionMatrix.m13 = D;
					this._projectionMatrix.m22 = q;
					this._projectionMatrix.m23 = qn;
					this._projectionMatrix.m33 = 1.0f;
				} // ortho
			} // if !_customProjectionMatrix

			// grab a reference to the current render system
			var renderSystem = Root.Instance.RenderSystem;
			// API specific
			renderSystem.ConvertProjectionMatrix( this._projectionMatrix, out this._projectionMatrixRS );
			// API specific for Gpu Programs
			renderSystem.ConvertProjectionMatrix( this._projectionMatrix, out this._projectionMatrixRSDepth, true );

			// Calculate bounding box (local)
			// Box is from 0, down -Z, max dimensions as determined from far plane
			// If infinite view frustum just pick a far value
			var farDist = ( this._farDistance == 0.0f ) ? InfiniteFarPlaneDistance : this._farDistance;

			// Near plane bounds
			var min = new Vector3( vpLeft, vpBottom, -farDist );
			var max = new Vector3( vpRight, vpTop, 0 );

			if ( this._customProjectionMatrix )
			{
				// Some custom projection matrices can have unusual inverted settings
				// So make sure the AABB is the right way around to start with
				var tmp = min;
				min.Floor( max );
				max.Ceil( tmp );
			}

			var radio = 1.0f;
			if ( this._projectionType == Projection.Perspective )
			{
				// Merge with far plane bounds
				radio = this._farDistance/this._nearDistance;
				min.Floor( new Vector3( vpLeft*radio, vpBottom*radio, -this._farDistance ) );
				max.Ceil( new Vector3( vpRight*radio, vpTop*radio, 0 ) );
			}

			this._boundingBox.SetExtents( min, max );

			this._recalculateFrustum = false;

			// Signal to update frustum clipping planes
			this._recalculateFrustumPlanes = true;
		}
Пример #14
0
        /// <summary>
        ///     Sets up the surface by defining it's control points, type and initial subdivision level.
        /// </summary>
        /// <remarks>
        ///     This method initialises the surface by passing it a set of control points. The type of curves to be used
        ///     are also defined here, although the only supported option currently is a bezier patch. You can also
        ///     specify a global subdivision level here if you like, although it is recommended that the parameter
        ///     is left as AUTO_LEVEL, which means the system decides how much subdivision is required (based on the
        ///     curvature of the surface).
        /// </remarks>
        /// <param name="controlPoints">
        ///     A pointer to a buffer containing the vertex data which defines control points
        ///     of the curves rather than actual vertices. Note that you are expected to provide not
        ///     just position information, but potentially normals and texture coordinates too. The
        ///     format of the buffer is defined in the VertexDeclaration parameter.
        /// </param>
        /// <param name="decl">
        ///     VertexDeclaration describing the contents of the buffer.
        ///     Note this declaration must _only_ draw on buffer source 0!
        /// </param>
        /// <param name="width">Specifies the width of the patch in control points.</param>
        /// <param name="height">Specifies the height of the patch in control points.</param>
        /// <param name="type">The type of surface.</param>
        /// <param name="uMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="vMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="side">Determines which side of the patch (or both) triangles are generated for.</param>
        public unsafe void DefineSurface(System.Array controlPointBuffer, VertexDeclaration declaration, int width, int height,
                                         PatchSurfaceType type, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide)
        {
            if (height == 0 || width == 0)
            {
                return; // Do nothing - garbage
            }

            this.type               = type;
            this.controlWidth       = width;
            this.controlHeight      = height;
            this.controlCount       = width * height;
            this.controlPointBuffer = controlPointBuffer;
            this.declaration        = declaration;

            // Copy positions into Vector3 vector
            controlPoints.Clear();
            VertexElement elem     = declaration.FindElementBySemantic(VertexElementSemantic.Position);
            int           vertSize = declaration.GetVertexSize(0);
            byte *        pVert    = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(controlPointBuffer, 0);
            float *       pReal    = null;

            for (int i = 0; i < controlCount; i++)
            {
                pReal = (float *)(pVert + elem.Offset);
                controlPoints.Add(new Vector3(pReal[0], pReal[1], pReal[2]));
                pVert += vertSize;
            }

            this.side = visibleSide;

            // Determine max level
            // Initialise to 100% detail
            subdivisionFactor = 1.0f;

            if (uMaxSubdivisionLevel == AUTO_LEVEL)
            {
                uLevel = maxULevel = GetAutoULevel();
            }
            else
            {
                uLevel = maxULevel = uMaxSubdivisionLevel;
            }

            if (vMaxSubdivisionLevel == AUTO_LEVEL)
            {
                vLevel = maxVLevel = GetAutoVLevel();
            }
            else
            {
                vLevel = maxVLevel = vMaxSubdivisionLevel;
            }

            // Derive mesh width / height
            meshWidth  = (LevelWidth(maxULevel) - 1) * ((controlWidth - 1) / 2) + 1;
            meshHeight = (LevelWidth(maxVLevel) - 1) * ((controlHeight - 1) / 2) + 1;

            // Calculate number of required vertices / indexes at max resolution
            requiredVertexCount = meshWidth * meshHeight;
            int iterations = (side == VisibleSide.Both)? 2 : 1;

            requiredIndexCount = (meshWidth - 1) * (meshHeight - 1) * 2 * iterations * 3;

            // Calculate bounds based on control points
            Vector3 min         = Vector3.Zero;
            Vector3 max         = Vector3.Zero;
            float   maxSqRadius = 0.0f;
            bool    first       = true;

            for (int i = 0; i < controlPoints.Count; i++)
            {
                Vector3 vec = controlPoints[i];
                if (first)
                {
                    min         = max = vec;
                    maxSqRadius = vec.LengthSquared;
                    first       = false;
                }
                else
                {
                    min.Floor(vec);
                    max.Ceil(vec);
                    maxSqRadius = MathUtil.Max(vec.LengthSquared, maxSqRadius);
                }
            }

            // set the bounds of the patch
            aabb.SetExtents(min, max);
            boundingSphereRadius = MathUtil.Sqrt(maxSqRadius);
        }
Пример #15
0
		/* Test if a scene node intersected a portal during the last time delta
			* (from last frame time to current frame time).  This function checks
			* if the node "crossed over" the portal also.
		*/
		public PortalIntersectResult intersects( PCZSceneNode pczsn )
		{
			// Only check if portal is open
			if ( mOpen )
			{
				if ( pczsn == mNode )
				{
					// ignore the scene node if it is the node the portal is associated with
					return PortalIntersectResult.NO_INTERSECT;
				}
				// most complicated case - if the portal is a quad:
				if ( mType == PORTAL_TYPE.PORTAL_TYPE_QUAD )
				{
					// the node is modeled as a line segment (prevPostion to currentPosition)
					// intersection test is then between the capsule and the line segment.
					Segment nodeSegment = new Segment();
					nodeSegment.Set( pczsn.PreviousPosition, pczsn.DerivedPosition );

					// we model the portal as a line swept sphere (mPrevDerivedCP to mDerivedCP).
					Capsule portalCapsule = new Capsule();
					portalCapsule.Set( mPrevDerivedCP, mDerivedCP, mRadius );

					if ( portalCapsule.Intersects( nodeSegment ) )
					{
						// the portal intersected the node at some time from last frame to this frame.
						// Now check if node "crossed" the portal
						// a crossing occurs if the "side" of the final position of the node compared
						// to the final position of the portal is negative AND the initial position
						// of the node compared to the initial position of the portal is non-negative
						if ( mDerivedPlane.GetSide( pczsn.DerivedPosition ) == PlaneSide.Negative &&
							mPrevDerivedPlane.GetSide( pczsn.DerivedPosition ) != PlaneSide.Negative )
						{
							// safety check - make sure the node has at least one dimension which is
							// small enough to fit through the portal! (avoid the "elephant fitting
							// through a mouse hole" case)
							Vector3 nodeHalfVector = pczsn.WorldAABB.HalfSize;
							Vector3 portalBox = new Vector3( mRadius, mRadius, mRadius );
							portalBox.Floor( nodeHalfVector );
							if ( portalBox.x < mRadius )
							{
								// crossing occurred!
								return PortalIntersectResult.INTERSECT_CROSS;
							}
						}
					}
					// there was no crossing of the portal by the node, but it might be touching
					// the portal.  We check for this by checking the bounding box of the node vs.
					// the sphere of the portal
					if ( mDerivedSphere.Intersects( pczsn.WorldAABB ) &&
						mDerivedPlane.GetSide( pczsn.WorldAABB ) == PlaneSide.Both )
					{
						// intersection but no crossing
						// note this means that the node is CURRENTLY touching the portal.
						if ( mDerivedPlane.GetSide( pczsn.DerivedPosition ) != PlaneSide.Negative )
						{
							// the node is on the positive (front) or exactly on the CP of the portal
							return PortalIntersectResult.INTERSECT_NO_CROSS;
						}
						else
						{
							// the node is on the negative (back) side of the portal - it might be in the wrong zone!
							return PortalIntersectResult.INTERSECT_BACK_NO_CROSS;
						}
					}
					// no intersection CURRENTLY.  (there might have been an intersection
					// during the time between last frame and this frame, but it wasn't a portal
					// crossing, and it isn't touching anymore, so it doesn't matter.
					return PortalIntersectResult.NO_INTERSECT;
				}
				else if ( mType == PORTAL_TYPE.PORTAL_TYPE_AABB )
				{
					// for aabb's we check if the center point went from being inside to being outside
					// the aabb (or vice versa) for crossing.
					AxisAlignedBox aabb = new AxisAlignedBox( mDerivedCorners[ 0 ], mDerivedCorners[ 1 ] );
					//bool previousInside = aabb.contains(pczsn->getPrevPosition());
					bool currentInside = aabb.Contains( pczsn.DerivedPosition );
					if ( mDirection == Vector3.UnitZ )
					{
						// portal norm is "outward" pointing, look for going from outside to inside
						//if (previousInside == false &&
						if ( currentInside == true )
						{
							return PortalIntersectResult.INTERSECT_CROSS;
						}
					}
					else
					{
						// portal norm is "inward" pointing, look for going from inside to outside
						//if (previousInside == true &&
						if ( currentInside == false )
						{
							return PortalIntersectResult.INTERSECT_CROSS;
						}
					}
					// doesn't cross, but might be touching.  This is a little tricky because we only
					// care if the node aab is NOT fully contained in the portal aabb because we consider
					// the surface of the portal aabb the actual 'portal'.  First, check to see if the
					// aab of the node intersects the aabb portal
					if ( aabb.Intersects( pczsn.WorldAABB ) )
					{
						// now check if the intersection between the two is not the same as the
						// full node aabb, if so, then this means that the node is not fully "contained"
						// which is what we are looking for.
						AxisAlignedBox overlap = aabb.Intersection( pczsn.WorldAABB );
						if ( overlap != pczsn.WorldAABB )
						{
							return PortalIntersectResult.INTERSECT_NO_CROSS;
						}
					}
					return PortalIntersectResult.NO_INTERSECT;
				}
				else
				{
					// for spheres we check if the center point went from being inside to being outside
					// the sphere surface (or vice versa) for crossing.
					//Real previousDistance2 = mPrevDerivedCP.squaredDistance(pczsn->getPrevPosition());
					Real currentDistance2 = mDerivedCP.DistanceSquared( pczsn.DerivedPosition );
					Real mRadius2 = mRadius * mRadius;
					if ( mDirection == Vector3.UnitZ )
					{
						// portal norm is "outward" pointing, look for going from outside to inside
						//if (previousDistance2 >= mRadius2 &&
						if ( currentDistance2 < mRadius2 )
						{
							return PortalIntersectResult.INTERSECT_CROSS;
						}
					}
					else
					{
						// portal norm is "inward" pointing, look for going from inside to outside
						//if (previousDistance2 < mRadius2 &&
						if ( currentDistance2 >= mRadius2 )
						{
							return PortalIntersectResult.INTERSECT_CROSS;
						}
					}
					// no crossing, but might be touching - check distance
					if ( System.Math.Sqrt( System.Math.Abs( mRadius2 - currentDistance2 ) ) <= mRadius )
					{
						return PortalIntersectResult.INTERSECT_NO_CROSS;
					}
					return PortalIntersectResult.NO_INTERSECT;
				}
			}
			return PortalIntersectResult.NO_INTERSECT;

		}
Пример #16
0
		/// <summary>
		///		Utility method for extruding a bounding box.
		/// </summary>
		/// <param name="box">Original bounding box, will be updated in-place.</param>
		/// <param name="lightPosition">4D light position in object space, when w=0.0f this
		/// represents a directional light</param>
		/// <param name="extrudeDistance">The distance to extrude.</param>
		protected virtual void ExtrudeBounds( AxisAlignedBox box, Vector4 lightPosition, float extrudeDistance )
		{
			Vector3 extrusionDir = Vector3.Zero;

			if ( lightPosition.w == 0 )
			{
				extrusionDir.x = -lightPosition.x;
				extrusionDir.y = -lightPosition.y;
				extrusionDir.z = -lightPosition.z;
				extrusionDir.Normalize();
				extrusionDir *= extrudeDistance;
				box.SetExtents( box.Minimum + extrusionDir, box.Maximum + extrusionDir );
			}
			else
			{
				Vector3[] corners = box.Corners;
				Vector3 vmin = new Vector3();
				Vector3 vmax = new Vector3();

				for ( int i = 0; i < 8; i++ )
				{
					extrusionDir.x = corners[ i ].x - lightPosition.x;
					extrusionDir.y = corners[ i ].y - lightPosition.y;
					extrusionDir.z = corners[ i ].z - lightPosition.z;
					extrusionDir.Normalize();
					extrusionDir *= extrudeDistance;
					Vector3 res = corners[ i ] + extrusionDir;

					if ( i == 0 )
					{
						vmin = res;
						vmax = res;
					}
					else
					{
						vmin.Floor( res );
						vmax.Ceil( res );
					}
				}

				box.SetExtents( vmin, vmax );
			}
		}
Пример #17
0
        /* Test if a scene node intersected a portal during the last time delta
         * (from last frame time to current frame time).  This function checks
         * if the node "crossed over" the portal also.
         */

        public PortalIntersectResult intersects(PCZSceneNode pczsn)
        {
            // Only check if portal is open
            if (this.mOpen)
            {
                if (pczsn == this.mNode)
                {
                    // ignore the scene node if it is the node the portal is associated with
                    return(PortalIntersectResult.NO_INTERSECT);
                }
                // most complicated case - if the portal is a quad:
                if (this.mType == PORTAL_TYPE.PORTAL_TYPE_QUAD)
                {
                    // the node is modeled as a line segment (prevPostion to currentPosition)
                    // intersection test is then between the capsule and the line segment.
                    var nodeSegment = new Segment();
                    nodeSegment.Set(pczsn.PreviousPosition, pczsn.DerivedPosition);

                    // we model the portal as a line swept sphere (mPrevDerivedCP to mDerivedCP).
                    var portalCapsule = new Capsule();
                    portalCapsule.Set(this.mPrevDerivedCP, this.mDerivedCP, this.mRadius);

                    if (portalCapsule.Intersects(nodeSegment))
                    {
                        // the portal intersected the node at some time from last frame to this frame.
                        // Now check if node "crossed" the portal
                        // a crossing occurs if the "side" of the final position of the node compared
                        // to the final position of the portal is negative AND the initial position
                        // of the node compared to the initial position of the portal is non-negative
                        if (this.mDerivedPlane.GetSide(pczsn.DerivedPosition) == PlaneSide.Negative &&
                            this.mPrevDerivedPlane.GetSide(pczsn.DerivedPosition) != PlaneSide.Negative)
                        {
                            // safety check - make sure the node has at least one dimension which is
                            // small enough to fit through the portal! (avoid the "elephant fitting
                            // through a mouse hole" case)
                            Vector3 nodeHalfVector = pczsn.WorldAABB.HalfSize;
                            var     portalBox      = new Vector3(this.mRadius, this.mRadius, this.mRadius);
                            portalBox.Floor(nodeHalfVector);
                            if (portalBox.x < this.mRadius)
                            {
                                // crossing occurred!
                                return(PortalIntersectResult.INTERSECT_CROSS);
                            }
                        }
                    }
                    // there was no crossing of the portal by the node, but it might be touching
                    // the portal.  We check for this by checking the bounding box of the node vs.
                    // the sphere of the portal
                    if (this.mDerivedSphere.Intersects(pczsn.WorldAABB) &&
                        this.mDerivedPlane.GetSide(pczsn.WorldAABB) == PlaneSide.Both)
                    {
                        // intersection but no crossing
                        // note this means that the node is CURRENTLY touching the portal.
                        if (this.mDerivedPlane.GetSide(pczsn.DerivedPosition) != PlaneSide.Negative)
                        {
                            // the node is on the positive (front) or exactly on the CP of the portal
                            return(PortalIntersectResult.INTERSECT_NO_CROSS);
                        }
                        else
                        {
                            // the node is on the negative (back) side of the portal - it might be in the wrong zone!
                            return(PortalIntersectResult.INTERSECT_BACK_NO_CROSS);
                        }
                    }
                    // no intersection CURRENTLY.  (there might have been an intersection
                    // during the time between last frame and this frame, but it wasn't a portal
                    // crossing, and it isn't touching anymore, so it doesn't matter.
                    return(PortalIntersectResult.NO_INTERSECT);
                }
                else if (this.mType == PORTAL_TYPE.PORTAL_TYPE_AABB)
                {
                    // for aabb's we check if the center point went from being inside to being outside
                    // the aabb (or vice versa) for crossing.
                    var aabb = new AxisAlignedBox(this.mDerivedCorners[0], this.mDerivedCorners[1]);
                    //bool previousInside = aabb.contains(pczsn->getPrevPosition());
                    bool currentInside = aabb.Contains(pczsn.DerivedPosition);
                    if (this.mDirection == Vector3.UnitZ)
                    {
                        // portal norm is "outward" pointing, look for going from outside to inside
                        //if (previousInside == false &&
                        if (currentInside == true)
                        {
                            return(PortalIntersectResult.INTERSECT_CROSS);
                        }
                    }
                    else
                    {
                        // portal norm is "inward" pointing, look for going from inside to outside
                        //if (previousInside == true &&
                        if (currentInside == false)
                        {
                            return(PortalIntersectResult.INTERSECT_CROSS);
                        }
                    }
                    // doesn't cross, but might be touching.  This is a little tricky because we only
                    // care if the node aab is NOT fully contained in the portal aabb because we consider
                    // the surface of the portal aabb the actual 'portal'.  First, check to see if the
                    // aab of the node intersects the aabb portal
                    if (aabb.Intersects(pczsn.WorldAABB))
                    {
                        // now check if the intersection between the two is not the same as the
                        // full node aabb, if so, then this means that the node is not fully "contained"
                        // which is what we are looking for.
                        AxisAlignedBox overlap = aabb.Intersection(pczsn.WorldAABB);
                        if (overlap != pczsn.WorldAABB)
                        {
                            return(PortalIntersectResult.INTERSECT_NO_CROSS);
                        }
                    }
                    return(PortalIntersectResult.NO_INTERSECT);
                }
                else
                {
                    // for spheres we check if the center point went from being inside to being outside
                    // the sphere surface (or vice versa) for crossing.
                    //Real previousDistance2 = mPrevDerivedCP.squaredDistance(pczsn->getPrevPosition());
                    Real currentDistance2 = this.mDerivedCP.DistanceSquared(pczsn.DerivedPosition);
                    Real mRadius2         = this.mRadius * this.mRadius;
                    if (this.mDirection == Vector3.UnitZ)
                    {
                        // portal norm is "outward" pointing, look for going from outside to inside
                        //if (previousDistance2 >= mRadius2 &&
                        if (currentDistance2 < mRadius2)
                        {
                            return(PortalIntersectResult.INTERSECT_CROSS);
                        }
                    }
                    else
                    {
                        // portal norm is "inward" pointing, look for going from inside to outside
                        //if (previousDistance2 < mRadius2 &&
                        if (currentDistance2 >= mRadius2)
                        {
                            return(PortalIntersectResult.INTERSECT_CROSS);
                        }
                    }
                    // no crossing, but might be touching - check distance
                    if (System.Math.Sqrt(System.Math.Abs(mRadius2 - currentDistance2)) <= this.mRadius)
                    {
                        return(PortalIntersectResult.INTERSECT_NO_CROSS);
                    }
                    return(PortalIntersectResult.NO_INTERSECT);
                }
            }
            return(PortalIntersectResult.NO_INTERSECT);
        }
Пример #18
0
        public override void Update(IUpdateArgs args)
        {
            ChunkCoordinates oldChunkCoordinates = new ChunkCoordinates(base.KnownPosition);
            bool             sprint = IsSprinting;
            bool             sneak  = IsSneaking;

            if (Controller.IsFreeCam && !CanFly)
            {
                Controller.IsFreeCam = false;
            }
            else if (CanFly)
            {
                IsFlying = Controller.IsFreeCam;
            }

            Controller.Update(args.GameTime);
            //KnownPosition.HeadYaw = KnownPosition.Yaw;

            if (IsSprinting && !sprint)
            {
                FOVModifier += 10;

                Network.EntityAction((int)EntityId, EntityAction.StartSprinting);
            }
            else if (!IsSprinting && sprint)
            {
                FOVModifier -= 10;

                Network.EntityAction((int)EntityId, EntityAction.StopSprinting);
            }

            if (IsSneaking != sneak)
            {
                if (IsSneaking)
                {
                    Network.EntityAction((int)EntityId, EntityAction.StartSneaking);
                }
                else
                {
                    Network.EntityAction((int)EntityId, EntityAction.StopSneaking);
                }
            }

            if (Controller.CheckInput)
            {
                var hitEntity = HitEntity;
                if (hitEntity != null && Controller.InputManager.IsPressed(InputCommand.LeftClick))
                {
                    if (_destroyingBlock)
                    {
                        StopBreakingBlock(forceCanceled: true);
                    }

                    InteractWithEntity(hitEntity, true);
                }
                else if (hitEntity != null && Controller.InputManager.IsPressed(InputCommand.RightClick))
                {
                    if (_destroyingBlock)
                    {
                        StopBreakingBlock(forceCanceled: true);
                    }

                    InteractWithEntity(hitEntity, false);
                }
                else if (hitEntity == null && !_destroyingBlock && Controller.InputManager.IsDown(InputCommand.LeftClick))                 //Destroying block.
                {
                    StartBreakingBlock();
                }
                else if (_destroyingBlock && Controller.InputManager.IsUp(InputCommand.LeftClick))
                {
                    StopBreakingBlock();
                }
                else if (_destroyingBlock && Controller.InputManager.IsDown(InputCommand.LeftClick))
                {
                    if (_destroyingTarget != new BlockCoordinates(Raytraced.Floor()))
                    {
                        StopBreakingBlock(true, true);

                        if (Gamemode != Gamemode.Creative)
                        {
                            StartBreakingBlock();
                        }
                    }
                }
                else if (Controller.InputManager.IsPressed(InputCommand.RightClick))
                {
                    bool handledClick = false;
                    // Log.Debug($"Right click!");
                    if (Inventory.MainHand != null && !(Inventory.MainHand is ItemAir))
                    {
                        handledClick = HandleRightClick(Inventory.MainHand, 0);
                    }

                    if (!handledClick && Inventory.OffHand != null && !(Inventory.OffHand is ItemAir))
                    {
                        handledClick = HandleRightClick(Inventory.OffHand, 1);
                    }

                    if (!handledClick)
                    {
                        var flooredAdj = AdjacentRaytrace.Floor();
                        var remainder  = new Vector3(AdjacentRaytrace.X - flooredAdj.X, AdjacentRaytrace.Y - flooredAdj.Y, AdjacentRaytrace.Z - flooredAdj.Z);
                        Network?.BlockPlaced(Raytraced, GetTargetFace(), 0, remainder);

                        handledClick = true;
                    }
                }
            }
            else if (_destroyingBlock)
            {
                StopBreakingBlock();
            }

            UpdateRayTracer();

            base.Update(args);
        }
Пример #19
0
		private void _generateCurvedPlaneVertexData( HardwareVertexBuffer vbuf, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 transform, bool firstTime, bool normals, Matrix4 rotation, float curvature, int numTexCoordSets, float xTexCoord, float yTexCoord, SubMesh subMesh, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength )
		{
			Vector3 vec;
			unsafe
			{
				// lock the vertex buffer
				IntPtr data = vbuf.Lock( BufferLocking.Discard );

				float* pData = (float*)data.ToPointer();

				for ( int y = 0; y <= ySegments; y++ )
				{
					for ( int x = 0; x <= xSegments; x++ )
					{
						// centered on origin
						vec.x = ( x * xSpace ) - halfWidth;
						vec.y = ( y * ySpace ) - halfHeight;

						// Here's where curved plane is different from standard plane.  Amazing, I know.
						Real diff_x = ( x - ( (Real)xSegments / 2 ) ) / (Real)xSegments;
						Real diff_y = ( y - ( (Real)ySegments / 2 ) ) / (Real)ySegments;
						Real dist = Utility.Sqrt( diff_x * diff_x + diff_y * diff_y );
						vec.z = ( -Utility.Sin( ( 1 - dist ) * ( Utility.PI / 2 ) ) * curvature ) + curvature;

						// Transform by orientation and distance
						Vector3 pos = transform.TransformAffine( vec );

						*pData++ = pos.x;
						*pData++ = pos.y;
						*pData++ = pos.z;

						// Build bounds as we go
						if ( firstTime )
						{
							min = vec;
							max = vec;
							maxSquaredLength = vec.LengthSquared;
							firstTime = false;
						}
						else
						{
							min.Floor( vec );
							max.Ceil( vec );
							maxSquaredLength = Utility.Max( maxSquaredLength, vec.LengthSquared );
						}

						if ( normals )
						{
							// This part is kinda 'wrong' for curved planes... but curved planes are
							//   very valuable outside sky planes, which don't typically need normals
							//   so I'm not going to mess with it for now.

							// Default normal is along unit Z
							//vec = Vector3::UNIT_Z;
							// Rotate
							vec = rotation.TransformAffine( vec );

							*pData++ = vec.x;
							*pData++ = vec.y;
							*pData++ = vec.z;
						}

						for ( int i = 0; i < numTexCoordSets; i++ )
						{
							*pData++ = x * xTexCoord;
							*pData++ = 1 - ( y * yTexCoord );
						} // for texCoords
					} // for x
				} // for y

				// unlock the buffer
				vbuf.Unlock();

				subMesh.useSharedVertices = true;

			} // unsafe
		}
Пример #20
0
        private void InitDebugInfo()
        {
            _debugInfo.AddDebugLeft(() =>
            {
                //FpsCounter.Update();
                //World.ChunkManager.GetPendingLightingUpdates(out int lowLight, out int midLight, out int highLight);

                double avg = 0;
                if (World.ChunkManager.TotalChunkUpdates > 0)
                {
                    avg = (World.ChunkManager.ChunkUpdateTime / World.ChunkManager.TotalChunkUpdates).TotalMilliseconds;
                }

                return
                ($"Alex {Alex.Version} ({Alex.FpsMonitor.Value:##} FPS, Chunk Updates: {World.EnqueuedChunkUpdates} queued, {World.ConcurrentChunkUpdates} active, Avg: {avg:F2}ms, Max: {World.ChunkManager.MaxUpdateTime.TotalMilliseconds:F2}ms, Min: {World.ChunkManager.MinUpdateTIme.TotalMilliseconds:F2})"                        /*, H: {highLight} M: {midLight} L: {lowLight} lighting updates)"*/
                );
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos      = World.Player.KnownPosition;
                var blockPos = pos.GetCoordinates3D();
                return($"RenderPosition: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) / Block: ({blockPos.X:D}, {blockPos.Y:D}, {blockPos.Z:D})");
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.KnownPosition;
                return($"Facing: {GetCardinalDirection(pos)} (HeadYaw={pos.HeadYaw:F2}, Yaw={pos.Yaw:F2}, Pitch={pos.Pitch:F2})");
            });
            _debugInfo.AddDebugLeft(() =>
            {
                var pos = World.Player.Velocity;
                return($"Velocity: (X={pos.X:F2}, Y={pos.Y:F2}, Z={pos.Z:F2}) / Target Speed: {World.Player.Controller.LastSpeedFactor:F2} M/s");
            });
            _debugInfo.AddDebugLeft(() => $"Vertices: {World.Vertices:N0} ({GetBytesReadable((long)(World.Vertices * BlockShaderVertex.VertexDeclaration.VertexStride))})");
            //	_debugInfo.AddDebugLeft(() => $"IndexBuffer Elements: {World.IndexBufferSize:N0} ({GetBytesReadable(World.IndexBufferSize * 4)})");
            _debugInfo.AddDebugLeft(() => $"Chunks: {World.ChunkCount}, {World.ChunkManager.RenderedChunks}");
            _debugInfo.AddDebugLeft(() => $"Entities: {World.EntityManager.EntityCount}, {World.EntityManager.EntitiesRendered}");
            _debugInfo.AddDebugLeft(() =>
            {
                return($"Biome: {_currentBiome.Name} ({_currentBiomeId})");
            });
            _debugInfo.AddDebugLeft(() => { return($"Do DaylightCycle: {World.DoDaylightcycle}"); });

            _debugInfo.AddDebugRight(() => Alex.OperatingSystem);
            _debugInfo.AddDebugRight(() => Alex.Gpu);
            _debugInfo.AddDebugRight(() => $"{Alex.DotnetRuntime}\n");
            //_debugInfo.AddDebugRight(() => MemoryUsageDisplay);
            _debugInfo.AddDebugRight(() => $"RAM: {GetBytesReadable(_ramUsage, 2)}");
            _debugInfo.AddDebugRight(() => $"GPU: {GetBytesReadable(GpuResourceManager.GetMemoryUsage, 2)}");
            _debugInfo.AddDebugRight(() =>
            {
                return
                ($"Threads: {(_threadsUsed):00}/{_maxThreads}");
            });
            _debugInfo.AddDebugRight(() =>
            {
                if (_raytracedBlock.Y > 0 && _raytracedBlock.Y < 256)
                {
                    var adj = Vector3.Floor(_adjacentBlock) - Vector3.Floor(_raytracedBlock);
                    adj.Normalize();

                    var face = adj.GetBlockFace();

                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine($"Target: {_raytracedBlock} Face: {face}");
                    sb.AppendLine(
                        $"Skylight: {World.GetSkyLight(_raytracedBlock)} Face Skylight: {World.GetSkyLight(_adjacentBlock)}");
                    sb.AppendLine(
                        $"Blocklight: {World.GetBlockLight(_raytracedBlock)} Face Blocklight: {World.GetBlockLight(_adjacentBlock)}");

                    //sb.AppendLine($"Skylight scheduled: {World.IsScheduled((int) _raytracedBlock.X, (int) _raytracedBlock.Y, (int) _raytracedBlock.Z)}");

                    foreach (var bs in World
                             .GetBlockStates((int)_raytracedBlock.X, (int)_raytracedBlock.Y, (int)_raytracedBlock.Z))
                    {
                        var blockstate = bs.State;
                        if (blockstate != null && blockstate.Block.Renderable)
                        {
                            sb.AppendLine($"{blockstate.Name} (S: {bs.Storage})");
                            if (blockstate.IsMultiPart)
                            {
                                sb.AppendLine($"MultiPart=true");
                                sb.AppendLine();

                                sb.AppendLine("Models:");

                                foreach (var model in blockstate.AppliedModels)
                                {
                                    sb.AppendLine(model);
                                }
                            }

                            var dict = blockstate.ToDictionary();

                            if (dict.Count > 0)
                            {
                                sb.AppendLine();
                                sb.AppendLine("Blockstate:");

                                foreach (var kv in dict)
                                {
                                    sb.AppendLine($"{kv.Key}={kv.Value}");
                                }
                            }
                        }
                    }

                    return(sb.ToString());
                }
                else
                {
                    return(string.Empty);
                }
            });

            _debugInfo.AddDebugRight(() =>
            {
                var player = World.Player;
                if (player == null || player.HitEntity == null)
                {
                    return(string.Empty);
                }

                var entity = player.HitEntity;
                return($"Hit entity: {entity.EntityId} / {entity.ToString()}");
            });
        }
Пример #21
0
		/// <summary>
		///		Update the bounds of the BillboardSet.
		/// </summary>
		public virtual void UpdateBounds()
		{
			if ( this.activeBillboards.Count == 0 )
			{
				// no billboards, so the bounding box is null
				this.aab.IsNull = true;
				this.boundingRadius = 0.0f;
			}
			else
			{
				float maxSqLen = -1.0f;
				Vector3 min = new Vector3( float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity );
				Vector3 max = new Vector3( float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity );

				foreach ( Billboard billboard in this.activeBillboards )
				{
					Vector3 pos = billboard.Position;
					min.Floor( pos );
					max.Ceil( pos );

					maxSqLen = Utility.Max( maxSqLen, pos.LengthSquared );
				}

				// adjust for billboard size
				float adjust = Utility.Max( this.defaultParticleWidth, this.defaultParticleHeight );
				Vector3 vecAdjust = new Vector3( adjust, adjust, adjust );
				min -= vecAdjust;
				max += vecAdjust;

				// update our local aabb
				this.aab.SetExtents( min, max );

				this.boundingRadius = Utility.Sqrt( maxSqLen );
			}
			// if we have a parent node, ask it to update us
			if ( this.parentNode != null )
			{
				this.parentNode.NeedUpdate();
			}
		}
        private static void GeneratePlaneVertexData(HardwareVertexBuffer vbuf, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 transform, bool firstTime, bool normals, Matrix4 rotation, int numTexCoordSets, float xTexCoord, float yTexCoord, SubMesh subMesh, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength)
        {
            Vector3 vec;

            unsafe {
                // lock the vertex buffer
                IntPtr data = vbuf.Lock(BufferLocking.Discard);

                float *pData = (float *)data.ToPointer();

                for (int y = 0; y <= ySegments; y++)
                {
                    for (int x = 0; x <= xSegments; x++)
                    {
                        // centered on origin
                        vec.x = (x * xSpace) - halfWidth;
                        vec.y = (y * ySpace) - halfHeight;
                        vec.z = 0.0f;

                        vec = transform * vec;

                        *pData++ = vec.x;
                        *pData++ = vec.y;
                        *pData++ = vec.z;

                        // Build bounds as we go
                        if (firstTime)
                        {
                            min = vec;
                            max = vec;
                            maxSquaredLength = vec.LengthSquared;
                            firstTime        = false;
                        }
                        else
                        {
                            min.Floor(vec);
                            max.Ceil(vec);
                            maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared);
                        }

                        if (normals)
                        {
                            vec = Vector3.UnitZ;
                            vec = rotation * vec;

                            *pData++ = vec.x;
                            *pData++ = vec.y;
                            *pData++ = vec.z;
                        }

                        for (int i = 0; i < numTexCoordSets; i++)
                        {
                            *pData++ = x * xTexCoord;
                            *pData++ = 1 - (y * yTexCoord);
                        } // for texCoords
                    }     // for x
                }         // for y

                // unlock the buffer
                vbuf.Unlock();

                subMesh.useSharedVertices = true;
            } // unsafe
        }