From e23b5aeda592a80ecd40e757f35c2176109fd16e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 3 Jul 2015 09:20:46 +1000 Subject: [PATCH] Move model size functionality to model classes. Add separate bounding boxes for collision and picking. Add function to rotate points around Y axis. --- Entities/Entity.cs | 39 +++++++++++++++++++++++++++++-------- Entities/EntityList.cs | 3 +-- Entities/LocalPlayer.cs | 7 +------ Entities/Player.cs | 8 -------- Model/BlockModel.cs | 9 +++++++++ Model/ChickenModel.cs | 8 ++++++++ Model/CreeperModel.cs | 9 +++++++++ Model/IModel.cs | 4 ++++ Model/PigModel.cs | 8 ++++++++ Model/PlayerModel.cs | 9 +++++++++ Model/SheepModel.cs | 8 ++++++++ Model/SkeletonModel.cs | 8 ++++++++ Model/SpiderModel.cs | 8 ++++++++ Model/ZombieModel.cs | 8 ++++++++ Network/NetworkProcessor.cs | 4 ++-- Physics/Entity.Physics.cs | 2 +- Rendering/PlayerRenderer.cs | 2 +- Utils/Utils.cs | 6 ++++++ 18 files changed, 122 insertions(+), 28 deletions(-) diff --git a/Entities/Entity.cs b/Entities/Entity.cs index 289c60d0c..776d5b49f 100644 --- a/Entities/Entity.cs +++ b/Entities/Entity.cs @@ -1,4 +1,5 @@ using System; +using ClassicalSharp.Model; using OpenTK; namespace ClassicalSharp { @@ -8,6 +9,7 @@ namespace ClassicalSharp { public Vector3 Position; public Vector3 Velocity; public float YawDegrees, PitchDegrees; + public IModel Model; public float YawRadians { get { return (float)Utils.DegreesToRadians( YawDegrees ); } @@ -25,17 +27,38 @@ namespace ClassicalSharp { } public abstract float StepSize { get; } - public abstract Vector3 Size { get; } + public virtual Vector3 CollisionSize { + get { return new Vector3( 8 / 16f, 30 / 16f, 8 / 16f ); + //Model.CollisionSize; TODO: for non humanoid models, we also need to offset eye position. + } + } - public virtual BoundingBox Bounds { + public virtual BoundingBox CollisionBounds { get { Vector3 pos = Position; - Vector3 size = Size; + Vector3 size = Model.CollisionSize; return new BoundingBox( pos.X - size.X / 2, pos.Y, pos.Z - size.Z / 2, pos.X + size.X / 2, pos.Y + size.Y, pos.Z + size.Z / 2 ); } } + public virtual BoundingBox PickingBounds { + get { + BoundingBox bb = Model.PickingBounds; + float angle = YawRadians; + // TODO: This would be a lot simpler and more accurate if we just did ray-oobb intersection. + Vector3 x1z1 = Utils.RotateY( bb.Min.X, 0, bb.Min.Z, angle ); + Vector3 x1z2 = Utils.RotateY( bb.Min.X, 0, bb.Max.Z, angle ); + Vector3 x2z1 = Utils.RotateY( bb.Max.X, 0, bb.Min.Z, angle ); + Vector3 x2z2 = Utils.RotateY( bb.Max.X, 0, bb.Max.Z, angle ); + float minX = Math.Min( x1z1.X, Math.Min( x1z2.X, Math.Min( x2z2.X, x2z1.X ) ) ); + float maxX = Math.Max( x1z1.X, Math.Max( x1z2.X, Math.Max( x2z2.X, x2z1.X ) ) ); + float minZ = Math.Min( x1z1.Z, Math.Min( x1z2.Z, Math.Min( x2z2.Z, x2z1.Z ) ) ); + float maxZ = Math.Max( x1z1.Z, Math.Max( x1z2.Z, Math.Max( x2z2.Z, x2z1.Z ) ) ); + return new BoundingBox( minX, bb.Min.Y, minZ, maxX, bb.Max.Y, maxZ ).Offset( Position ); + } + } + public abstract void Despawn(); public abstract void Render( double deltaTime, float t ); @@ -52,15 +75,15 @@ namespace ClassicalSharp { return TouchesAny( b => b == (byte)Block.Water || b == (byte)Block.StillWater ); } - public bool TouchesAnyOf( byte blockType ) { + public bool TouchesAnyOf( byte blockType ) { return TouchesAny( b => b == blockType ); } - public bool TouchesAny( Predicate condition ) { - BoundingBox bounds = Bounds; + public bool TouchesAny( Predicate condition ) { + BoundingBox bounds = CollisionBounds; Vector3I bbMin = Vector3I.Floor( bounds.Min ); Vector3I bbMax = Vector3I.Floor( bounds.Max ); - + for( int x = bbMin.X; x <= bbMax.X; x++ ) { for( int y = bbMin.Y; y <= bbMax.Y; y++ ) { for( int z = bbMin.Z; z <= bbMax.Z; z++ ) { @@ -74,7 +97,7 @@ namespace ClassicalSharp { if( blockBB.Intersects( bounds ) ) return true; } } - } + } } return false; } diff --git a/Entities/EntityList.cs b/Entities/EntityList.cs index 5179b463b..cc48a9441 100644 --- a/Entities/EntityList.cs +++ b/Entities/EntityList.cs @@ -39,8 +39,7 @@ namespace ClassicalSharp { for( int i = 0; i < Players.Length - 1; i++ ) { // -1 because we don't want to pick against local player Player p = Players[i]; if( p == null ) continue; - BoundingBox bounds = p.Bounds; - + BoundingBox bounds = p.PickingBounds; float t0, t1; if( IntersectionUtils.RayIntersectsBox( eyePos, dir, bounds.Min, bounds.Max, out t0, out t1 ) ) { dist = t0; diff --git a/Entities/LocalPlayer.cs b/Entities/LocalPlayer.cs index 80a48980a..4db5db1ea 100644 --- a/Entities/LocalPlayer.cs +++ b/Entities/LocalPlayer.cs @@ -174,12 +174,7 @@ namespace ClassicalSharp { if( dist < 1 ) dist = 1; float multiply = factor / dist; - x *= multiply; - z *= multiply; - float cosA = (float)Math.Cos( YawRadians ); - float sinA = (float)Math.Sin( YawRadians ); - Velocity.X += x * cosA - z * sinA; - Velocity.Z += x * sinA + z * cosA; + Velocity += Utils.RotateY( x * multiply, 0, z * multiply, YawRadians ); } void Move( float xMoving, float zMoving, float factor, Vector3 drag, float gravity, float yMul ) { diff --git a/Entities/Player.cs b/Entities/Player.cs index 8a5a8738f..93ae019b2 100644 --- a/Entities/Player.cs +++ b/Entities/Player.cs @@ -9,14 +9,7 @@ namespace ClassicalSharp { public abstract class Player : Entity { - public const float Width = 0.6f; public const float EyeHeight = 1.625f; - public const float Height = 1.8f; - public const float Depth = 0.6f; - - public override Vector3 Size { - get { return new Vector3( Width, Height, Depth ); } - } /// Gets the position of the player's eye in the world. public Vector3 EyePosition { @@ -31,7 +24,6 @@ namespace ClassicalSharp { public byte ID; public string DisplayName, SkinName; public string ModelName; - public IModel Model; protected PlayerRenderer renderer; public SkinType SkinType; diff --git a/Model/BlockModel.cs b/Model/BlockModel.cs index 5dae1880a..1229e0cc4 100644 --- a/Model/BlockModel.cs +++ b/Model/BlockModel.cs @@ -18,6 +18,15 @@ namespace ClassicalSharp.Model { get { return blockHeight + 0.075f; } } + const float adjust = 0.1f; + public override Vector3 CollisionSize { + get { return new Vector3( 1 - adjust, blockHeight - adjust, 1 - adjust ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -0.5f, 0f, -0.5f, 0.5f, blockHeight, 0.5f ); } + } + protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; graphics.AlphaTest = true; diff --git a/Model/ChickenModel.cs b/Model/ChickenModel.cs index 1e42e516a..4054d61ef 100644 --- a/Model/ChickenModel.cs +++ b/Model/ChickenModel.cs @@ -58,6 +58,14 @@ namespace ClassicalSharp.Model { get { return 1.0125f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 8 / 16f, 12 / 16f, 8 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -4 / 16f, 0, -8 / 16f, 4 / 16f, 15 / 16f, 4 / 16f ); } + } + protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId; diff --git a/Model/CreeperModel.cs b/Model/CreeperModel.cs index 8f76e90fc..d0598be02 100644 --- a/Model/CreeperModel.cs +++ b/Model/CreeperModel.cs @@ -1,6 +1,7 @@ using System; using ClassicalSharp.GraphicsAPI; using ClassicalSharp.Renderers; +using OpenTK; namespace ClassicalSharp.Model { @@ -39,6 +40,14 @@ namespace ClassicalSharp.Model { get { return 1.7f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 8 / 16f, 26 / 16f, 8 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -4 / 16f, 0, -6 / 16f, 4 / 16f, 26 / 16f, 6 / 16f ); } + } + protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId; diff --git a/Model/IModel.cs b/Model/IModel.cs index e38c4e3e2..ad199f486 100644 --- a/Model/IModel.cs +++ b/Model/IModel.cs @@ -19,6 +19,10 @@ namespace ClassicalSharp.Model { public abstract float NameYOffset { get; } + public abstract Vector3 CollisionSize { get; } + + public abstract BoundingBox PickingBounds { get; } + protected Vector3 pos; protected float yaw, pitch; protected float rightLegXRot, rightArmXRot, rightArmZRot; diff --git a/Model/PigModel.cs b/Model/PigModel.cs index e4f1425d6..a86526f17 100644 --- a/Model/PigModel.cs +++ b/Model/PigModel.cs @@ -41,6 +41,14 @@ namespace ClassicalSharp.Model { get { return 1.075f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 14 / 16f, 14 / 16f, 14 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -5 / 16f, 0, -14 / 16f, 5 / 16f, 16 / 16f, 9 / 16f ); } + } + protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId; diff --git a/Model/PlayerModel.cs b/Model/PlayerModel.cs index bee689958..73a1ccf0c 100644 --- a/Model/PlayerModel.cs +++ b/Model/PlayerModel.cs @@ -2,6 +2,7 @@ using System.Drawing; using ClassicalSharp.GraphicsAPI; using ClassicalSharp.Renderers; +using OpenTK; namespace ClassicalSharp.Model { @@ -81,6 +82,14 @@ namespace ClassicalSharp.Model { get { return 2.1375f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 8 / 16f, 30 / 16f, 8 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -8 / 16f, 0, -4 / 16f, 8 / 16f, 32 / 16f, 4 / 16f ); } + } + ModelSet model; protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; diff --git a/Model/SheepModel.cs b/Model/SheepModel.cs index 1f288001a..45c29198b 100644 --- a/Model/SheepModel.cs +++ b/Model/SheepModel.cs @@ -65,6 +65,14 @@ namespace ClassicalSharp.Model { get { return Fur ? 1.48125f: 1.075f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 14 / 16f, 20 / 16f, 14 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -6 / 16f, 0, -13 / 16f, 6 / 16f, 23 / 16f, 10 / 16f ); } + } + protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId; diff --git a/Model/SkeletonModel.cs b/Model/SkeletonModel.cs index 36e85a643..7da7d2580 100644 --- a/Model/SkeletonModel.cs +++ b/Model/SkeletonModel.cs @@ -53,6 +53,14 @@ namespace ClassicalSharp.Model { get { return 2.075f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 8 / 16f, 30 / 16f, 8 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -4 / 16f, 0, -4 / 16f, 4 / 16f, 32 / 16f, 4 / 16f ); } + } + protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; graphics.AlphaTest = true; diff --git a/Model/SpiderModel.cs b/Model/SpiderModel.cs index 8fb03a17a..0181013c6 100644 --- a/Model/SpiderModel.cs +++ b/Model/SpiderModel.cs @@ -44,6 +44,14 @@ namespace ClassicalSharp.Model { get { return 1.0125f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 15 / 16f, 12 / 16f, 15 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -5 / 16f, 0, -11 / 16f, 5 / 16f, 12 / 16f, 15 / 16f ); } + } + const float quarterPi = (float)( Math.PI / 4 ); const float eighthPi = (float)( Math.PI / 8 ); protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { diff --git a/Model/ZombieModel.cs b/Model/ZombieModel.cs index 974a5c544..d7d5d5dbf 100644 --- a/Model/ZombieModel.cs +++ b/Model/ZombieModel.cs @@ -53,6 +53,14 @@ namespace ClassicalSharp.Model { get { return 2.075f; } } + public override Vector3 CollisionSize { + get { return new Vector3( 8 / 16f, 30 / 16f, 8 / 16f ); } + } + + public override BoundingBox PickingBounds { + get { return new BoundingBox( -4 / 16f, 0, -4 / 16f, 4 / 16f, 32 / 16f, 4 / 16f ); } + } + protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) { graphics.Texturing = true; int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId; diff --git a/Network/NetworkProcessor.cs b/Network/NetworkProcessor.cs index d4c5257e5..37eda2c65 100644 --- a/Network/NetworkProcessor.cs +++ b/Network/NetworkProcessor.cs @@ -182,7 +182,7 @@ namespace ClassicalSharp { } private static void MakePlayerClick( byte button, bool buttonDown, float yaw, float pitch, byte targetEntity, - Vector3I targetPos, CpeBlockFace targetFace ) { + Vector3I targetPos, CpeBlockFace targetFace ) { WriteUInt8( (byte)PacketId.CpePlayerClick ); WriteUInt8( button ); WriteUInt8( buttonDown ? (byte)0 : (byte)1 ); @@ -226,7 +226,7 @@ namespace ClassicalSharp { void SendPacket() { int packetLength = outIndex; outIndex = 0; - if( Disconnected ) return; + if( Disconnected ) return; try { stream.Write( outBuffer, 0, packetLength ); diff --git a/Physics/Entity.Physics.cs b/Physics/Entity.Physics.cs index 2512cd2b2..d4f93d0ad 100644 --- a/Physics/Entity.Physics.cs +++ b/Physics/Entity.Physics.cs @@ -61,7 +61,7 @@ namespace ClassicalSharp { protected void MoveAndWallSlide() { if( Velocity == Vector3.Zero ) return; - Vector3 size = Size; + Vector3 size = CollisionSize; BoundingBox entityBB, entityExtentBB; int count = 0; FindReachableBlocks( ref count, ref size, out entityBB, out entityExtentBB ); diff --git a/Rendering/PlayerRenderer.cs b/Rendering/PlayerRenderer.cs index c2c4afcdc..48f1c2a01 100644 --- a/Rendering/PlayerRenderer.cs +++ b/Rendering/PlayerRenderer.cs @@ -25,7 +25,7 @@ namespace ClassicalSharp.Renderers { using( Font font = new Font( "Arial", 14 ) ) { List parts = Utils2D.SplitText( Graphics, player.DisplayName, true ); Size size = Utils2D.MeasureSize( parts, font, true ); - nameTexture = Utils2D.MakeTextTexture( parts, font, size, 0, 0 ); + nameTexture = Utils2D.MakeTextTexture( parts, font, size, 0, 0 ); nameWidth = size.Width; nameHeight = size.Height; nameTextureId = nameTexture.ID; diff --git a/Utils/Utils.cs b/Utils/Utils.cs index 6d5a2bb42..5f47c64da 100644 --- a/Utils/Utils.cs +++ b/Utils/Utils.cs @@ -111,6 +111,12 @@ namespace ClassicalSharp { return packed * 360.0 / 256.0; } + public static Vector3 RotateY( float x, float y, float z, float angle ) { + float cosA = (float)Math.Cos( angle ); + float sinA = (float)Math.Sin( angle ); + return new Vector3( cosA * x - sinA * z, y, sinA * x + cosA * z ); + } + public static float DistanceSquared( Vector3 p1, Vector3 p2 ) { float dx = p2.X - p1.X; float dy = p2.Y - p1.Y;