Fixed circle rendering and added 2D circle collider

This commit is contained in:
Simon Lübeß
2022-11-26 12:17:31 +01:00
parent 0155a38ae6
commit 8f22cbb8bc
7 changed files with 240 additions and 17 deletions
+64 -3
View File
@@ -18,7 +18,8 @@
Y = 0, Y = 0,
Z = 1, Z = 1,
W = 1 W = 1
} },
IsCircle = false
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
@@ -79,7 +80,8 @@
Y = 0, Y = 0,
Z = 1, Z = 1,
W = 1 W = 1
} },
IsCircle = false
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
@@ -160,9 +162,68 @@
OrthographicHeight = 10, OrthographicHeight = 10,
OrthographicNearPlane = 0, OrthographicNearPlane = 0,
OrthographicFarPlane = 10, OrthographicFarPlane = 10,
AspectRatio = 2.864979, AspectRatio = 2.01173,
FixedAspectRatio = false FixedAspectRatio = false
} }
},
{
Id = 15710354273720487680,
NameComponent = {
Name = "Circle"
},
SpriterRendererComponent = {
Color = {
R = 1,
G = 0,
B = 0,
A = 1
},
UvTransform = {
X = 0,
Y = 0,
Z = 1,
W = 1
},
IsCircle = true
},
TransformComponent = {
Position = {
X = -0.121203,
Y = 0.66016,
Z = 0
},
Rotation = {
X = 0,
Y = 0,
Z = 0,
W = 1
},
Scale = {
X = 1,
Y = 1,
Z = 1
},
EditorEulerRotation = {
X = 0,
Y = 0,
Z = 0
}
},
Rigidbody2D = {
BodyType = .Dynamic,
FixedRotation = false
},
CircleCollider2D = {
Offset = {
X = 0,
Y = 0
},
Radius = 0.5,
Density = 1,
Friction = 0.5,
Restitution = 0,
RestitutionThreshold = 0.5
}
} }
] ]
} }
+30 -4
View File
@@ -1,3 +1,5 @@
#define EDITOR
Texture2D Texture : register(t0); Texture2D Texture : register(t0);
SamplerState Sampler : register(s0); SamplerState Sampler : register(s0);
@@ -14,6 +16,9 @@ struct VS_Input
float4 Color : COLOR; float4 Color : COLOR;
float4 UVTransform : TEXCOORD1; float4 UVTransform : TEXCOORD1;
float InnerRadius : TEXCOORD2; float InnerRadius : TEXCOORD2;
#ifdef EDITOR
uint EntityId : ENTITYID;
#endif
}; };
struct PS_Input struct PS_Input
@@ -22,6 +27,9 @@ struct PS_Input
float2 RawPos : TEXCOORD0; float2 RawPos : TEXCOORD0;
float2 Texcoord : TEXCOORD1; float2 Texcoord : TEXCOORD1;
float4 Color : COLOR; float4 Color : COLOR;
#ifdef EDITOR
nointerpolation uint EntityId : ENTITYID;
#endif
float InnerRadius : TEXCOORD2; float InnerRadius : TEXCOORD2;
}; };
@@ -35,11 +43,25 @@ PS_Input VS(VS_Input input)
output.Color = input.Color; output.Color = input.Color;
output.InnerRadius = input.InnerRadius; output.InnerRadius = input.InnerRadius;
#ifdef EDITOR
output.EntityId = input.EntityId;
#endif
return output; return output;
} }
float4 PS(PS_Input input) : SV_Target0 struct PS_Output
{ {
float4 Color : SV_Target0;
#ifdef EDITOR
uint EntityId : SV_TARGET1;
#endif
};
PS_Output PS(PS_Input input)
{
PS_Output output;
float2 uv = input.RawPos * 2; float2 uv = input.RawPos * 2;
float distance = 1.0f - length(uv); float distance = 1.0f - length(uv);
@@ -53,10 +75,14 @@ float4 PS(PS_Input input) : SV_Target0
// Discard invisible pixels // Discard invisible pixels
clip(amount - 0.5f); clip(amount - 0.5f);
float4 color = Texture.Sample(Sampler, input.Texcoord) * input.Color; output.Color = Texture.Sample(Sampler, input.Texcoord) * input.Color;
color.a *= amount; output.Color.a *= amount;
return color; #ifdef EDITOR
output.EntityId = input.EntityId;
#endif
return output;
} }
#pragma Effect[VS=VS; PS=PS] #pragma Effect[VS=VS; PS=PS]
@@ -66,6 +66,7 @@ namespace GlitchyEditor.EditWindows
ShowComponentEditor<MeshComponent>("Mesh", entity, => ShowMeshComponentEditor, => ShowComponentContextMenu<MeshComponent>); ShowComponentEditor<MeshComponent>("Mesh", entity, => ShowMeshComponentEditor, => ShowComponentContextMenu<MeshComponent>);
ShowComponentEditor<Rigidbody2DComponent>("Rigidbody 2D", entity, => ShowRigidBody2DComponentEditor, => ShowComponentContextMenu<Rigidbody2DComponent>); ShowComponentEditor<Rigidbody2DComponent>("Rigidbody 2D", entity, => ShowRigidBody2DComponentEditor, => ShowComponentContextMenu<Rigidbody2DComponent>);
ShowComponentEditor<BoxCollider2DComponent>("Box collider 2D", entity, => ShowBoxCollider2DComponentEditor, => ShowComponentContextMenu<BoxCollider2DComponent>); ShowComponentEditor<BoxCollider2DComponent>("Box collider 2D", entity, => ShowBoxCollider2DComponentEditor, => ShowComponentContextMenu<BoxCollider2DComponent>);
ShowComponentEditor<CircleCollider2DComponent>("Circle collider 2D", entity, => ShowCircleCollider2DComponentEditor, => ShowComponentContextMenu<CircleCollider2DComponent>);
ShowAddComponentButton(entity); ShowAddComponentButton(entity);
} }
@@ -278,6 +279,8 @@ namespace GlitchyEditor.EditWindows
ImGui.EditVector<4>("UV Transform", ref *(float[4]*)&spriteRendererComponent.UvTransform); ImGui.EditVector<4>("UV Transform", ref *(float[4]*)&spriteRendererComponent.UvTransform);
ImGui.Checkbox("Is Circle", &spriteRendererComponent.IsCircle);
} }
private static void ShowMeshRendererComponentEditor(Entity entity, MeshRendererComponent* meshRendererComponent) private static void ShowMeshRendererComponentEditor(Entity entity, MeshRendererComponent* meshRendererComponent)
@@ -471,6 +474,37 @@ namespace GlitchyEditor.EditWindows
boxCollider.RestitutionThreshold = restitutionThreshold; boxCollider.RestitutionThreshold = restitutionThreshold;
} }
private static void ShowCircleCollider2DComponentEditor(Entity entity, CircleCollider2DComponent* circleCollider)
{
float textWidth = ImGui.CalcTextSize("Offset".CStr()).x;
textWidth += ImGui.GetStyle().FramePadding.x * 3.0f;
Vector2 offset = circleCollider.Offset;
if (ImGui.EditVector2("Offset", ref offset, .Zero, 0.1f, textWidth))
circleCollider.Offset = offset;
float radius = circleCollider.Radius;
if (ImGui.DragFloat("Radius", &radius, 0.0f, 0.1f, textWidth))
circleCollider.Radius = radius;
float density = circleCollider.Density;
if (ImGui.DragFloat("Density", &density, 0.0f, 0.1f, textWidth))
circleCollider.Density = density;
float friction = circleCollider.Friction;
if (ImGui.DragFloat("Friction", &friction, 0.0f, 0.1f, textWidth))
circleCollider.Friction = friction;
float restitution = circleCollider.Restitution;
if (ImGui.DragFloat("Restitution", &restitution, 0.0f, 0.1f, textWidth))
circleCollider.Restitution = restitution;
float restitutionThreshold = circleCollider.RestitutionThreshold;
if (ImGui.DragFloat("RestitutionThreshold", &restitutionThreshold, 0.0f, 0.1f, textWidth))
circleCollider.RestitutionThreshold = restitutionThreshold;
}
private static void LabelColumn(StringView label) private static void LabelColumn(StringView label)
{ {
ImGui.TextUnformatted(label); ImGui.TextUnformatted(label);
@@ -613,6 +647,7 @@ namespace GlitchyEditor.EditWindows
ShowComponentButton<LightComponent>("Light"); ShowComponentButton<LightComponent>("Light");
ShowComponentButton<Rigidbody2DComponent>("Rigidbody 2D"); ShowComponentButton<Rigidbody2DComponent>("Rigidbody 2D");
ShowComponentButton<BoxCollider2DComponent>("Box collider 2D"); ShowComponentButton<BoxCollider2DComponent>("Box collider 2D");
ShowComponentButton<CircleCollider2DComponent>("Circle collider 2D");
ImGui.EndCombo(); ImGui.EndCombo();
} }
+8 -5
View File
@@ -236,8 +236,8 @@ namespace GlitchyEngine.Renderer
VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 3, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 3, 1, (.)-1, .PerInstanceData, 1),
VertexElement(.R32G32B32A32_Float, "COLOR", false, 0, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "COLOR", false, 0, 1, (.)-1, .PerInstanceData, 1),
VertexElement(.R32G32B32A32_Float, "TEXCOORD", false, 1, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "TEXCOORD", false, 1, 1, (.)-1, .PerInstanceData, 1),
VertexElement(.R32_Float, "TEXCOORD", false, 2, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32_UInt, "ENTITYID", false, 0, 1, (.)-1, .PerInstanceData, 1),
VertexElement(.R32_UInt, "ENTITYID", false, 0, 1, (.)-1, .PerInstanceData, 1) VertexElement(.R32_Float, "TEXCOORD", false, 2, 1, (.)-1, .PerInstanceData, 1)
); );
s_circleBatchBinding = new GeometryBinding(); s_circleBatchBinding = new GeometryBinding();
@@ -873,7 +873,10 @@ namespace GlitchyEngine.Renderer
public static void DrawSprite(Matrix transform, SpriterRendererComponent* spriteRenderer, uint32 entityId) public static void DrawSprite(Matrix transform, SpriterRendererComponent* spriteRenderer, uint32 entityId)
{ {
DrawQuad(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, spriteRenderer.UvTransform, entityId); if (spriteRenderer.IsCircle)
DrawCircle(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, 1.0f, spriteRenderer.UvTransform, entityId);
else
DrawQuad(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, spriteRenderer.UvTransform, entityId);
} }
// Textured quad pivot // Textured quad pivot
@@ -912,7 +915,7 @@ namespace GlitchyEngine.Renderer
DrawCircle(transform, texture, color, innerRadius, uvTransform); DrawCircle(transform, texture, color, innerRadius, uvTransform);
} }
public static void DrawCircle(Matrix transform, Texture2D texture, ColorRGBA color = .White, float innerRadius = 1.0f, Vector4 uvTransform = .(0, 0, 1, 1)) public static void DrawCircle(Matrix transform, Texture2D texture, ColorRGBA color = .White, float innerRadius = 1.0f, Vector4 uvTransform = .(0, 0, 1, 1), uint32 entityId = uint32.MaxValue)
{ {
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
@@ -920,7 +923,7 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene."); Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene.");
#endif #endif
QueueCircleInstance(transform, color, texture, transform.Translation.Z, uvTransform, innerRadius); QueueCircleInstance(transform, color, texture, transform.Translation.Z, uvTransform, innerRadius, entityId);
if(s_drawOrder == .Immediate) if(s_drawOrder == .Immediate)
{ {
+50 -2
View File
@@ -2,6 +2,7 @@ using System;
using GlitchyEngine.Math; using GlitchyEngine.Math;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
using GlitchyEngine.Core; using GlitchyEngine.Core;
using Box2D;
namespace GlitchyEngine.World namespace GlitchyEngine.World
{ {
@@ -49,6 +50,8 @@ namespace GlitchyEngine.World
public ColorRGBA Color = .White; public ColorRGBA Color = .White;
public Vector4 UvTransform = .(0, 0, 1, 1); public Vector4 UvTransform = .(0, 0, 1, 1);
public bool IsCircle = false;
public this() public this()
{ {
} }
@@ -363,7 +366,15 @@ namespace GlitchyEngine.World
public bool FixedRotation = false; public bool FixedRotation = false;
internal int _runtimeBody = 0; private int _runtimeBody = 0;
internal b2Body* RuntimeBody
{
[Inline]
get => (b2Body*)(void*)_runtimeBody;
[Inline]
set mut => _runtimeBody = (int)(void*)value;
}
} }
struct BoxCollider2DComponent struct BoxCollider2DComponent
@@ -377,6 +388,43 @@ namespace GlitchyEngine.World
public float Restitution = 0.0f; public float Restitution = 0.0f;
public float RestitutionThreshold = 0.5f; public float RestitutionThreshold = 0.5f;
internal int _runtimeFixture = 0; private int _runtimeFixture = 0;
internal b2Fixture* RuntimeFixture
{
[Inline]
get => (b2Fixture*)(void*)_runtimeFixture;
[Inline]
set mut => _runtimeFixture = (int)(void*)value;
}
[Inline]
internal ref b2Vec2 b2Offset mut => ref *(Box2D.b2Vec2*)(void*)&Offset;
}
struct CircleCollider2DComponent
{
public Vector2 Offset = .(0.0f, 0.0f);
public float Radius = 0.5f;
// TODO: move into 2D physics material
public float Density = 1.0f;
public float Friction = 0.5f;
public float Restitution = 0.0f;
public float RestitutionThreshold = 0.5f;
private int _runtimeFixture = 0;
internal b2Fixture* RuntimeFixture
{
[Inline]
get => (b2Fixture*)(void*)_runtimeFixture;
[Inline]
set mut => _runtimeFixture = (int)(void*)value;
}
[Inline]
internal ref b2Vec2 b2Offset mut => ref *(Box2D.b2Vec2*)(void*)&Offset;
} }
} }
+21 -3
View File
@@ -121,12 +121,13 @@ namespace GlitchyEngine.World
b2Body* body = Box2D.World.CreateBody(_physicsWorld2D, &def); b2Body* body = Box2D.World.CreateBody(_physicsWorld2D, &def);
Box2D.Body.SetFixedRotation(body, rigidBody.FixedRotation); Box2D.Body.SetFixedRotation(body, rigidBody.FixedRotation);
rigidBody._runtimeBody = (int)(void*)body; rigidBody.RuntimeBody = body;
if (entity.TryGetComponent<BoxCollider2DComponent>(let boxCollider)) if (entity.TryGetComponent<BoxCollider2DComponent>(let boxCollider))
{ {
b2Shape* boxShape = Box2D.Shape.CreatePolygon(); b2Shape* boxShape = Box2D.Shape.CreatePolygon();
Box2D.Shape.PolygonSetAsBox(boxShape, boxCollider.Size.X * transform.Scale.X, boxCollider.Size.Y * transform.Scale.Y); Box2D.Shape.PolygonSetAsBox(boxShape, boxCollider.Size.X * transform.Scale.X, boxCollider.Size.Y * transform.Scale.Y);
Box2D.Shape.PolygonSetAsBoxWithCenterAngle(boxShape, boxCollider.Size.X * transform.Scale.X, boxCollider.Size.Y * transform.Scale.Y, ref boxCollider.b2Offset, 0.0f);
b2FixtureDef fixtureDef = .(); b2FixtureDef fixtureDef = .();
fixtureDef.shape = boxShape; fixtureDef.shape = boxShape;
@@ -136,7 +137,24 @@ namespace GlitchyEngine.World
fixtureDef.restitutionThreshold = boxCollider.RestitutionThreshold; fixtureDef.restitutionThreshold = boxCollider.RestitutionThreshold;
b2Fixture* fixture = Box2D.Body.CreateFixture(body, &fixtureDef); b2Fixture* fixture = Box2D.Body.CreateFixture(body, &fixtureDef);
boxCollider._runtimeFixture = (int)(void*)fixture; boxCollider.RuntimeFixture = fixture;
}
if (entity.TryGetComponent<CircleCollider2DComponent>(let circleCollider))
{
b2Shape* circleShape = Box2D.Shape.CreateCircle();
Box2D.Shape.CircleSetPosition(circleShape, ref circleCollider.b2Offset);
Box2D.Shape.SetRadius(circleShape, circleCollider.Radius);
b2FixtureDef fixtureDef = .();
fixtureDef.shape = circleShape;
fixtureDef.density = circleCollider.Density;
fixtureDef.friction = circleCollider.Friction;
fixtureDef.restitution = circleCollider.Restitution;
fixtureDef.restitutionThreshold = circleCollider.RestitutionThreshold;
b2Fixture* fixture = Box2D.Body.CreateFixture(body, &fixtureDef);
circleCollider.RuntimeFixture = fixture;
} }
} }
} }
@@ -184,7 +202,7 @@ namespace GlitchyEngine.World
var transform = entity.Transform; var transform = entity.Transform;
var rigidbody = entry.Component; var rigidbody = entry.Component;
b2Body* body = (b2Body*)(void*)rigidbody._runtimeBody; b2Body* body = rigidbody.RuntimeBody;
b2Vec2 position = Box2D.Body.GetPosition(body); b2Vec2 position = Box2D.Body.GetPosition(body);
float angle = Box2D.Body.GetAngle(body); float angle = Box2D.Body.GetAngle(body);
@@ -88,6 +88,7 @@ namespace GlitchyEngine.World
Serialize.Value(writer, "Color", component.Color); Serialize.Value(writer, "Color", component.Color);
Serialize.Value(writer, "UvTransform", component.UvTransform); Serialize.Value(writer, "UvTransform", component.UvTransform);
Serialize.Value(writer, "IsCircle", component.IsCircle);
}); });
SerializeComponent<TransformComponent>(writer, entity, "TransformComponent", scope (component) => SerializeComponent<TransformComponent>(writer, entity, "TransformComponent", scope (component) =>
@@ -156,6 +157,17 @@ namespace GlitchyEngine.World
Serialize.Value(writer, "Restitution", component.Restitution); Serialize.Value(writer, "Restitution", component.Restitution);
Serialize.Value(writer, "RestitutionThreshold", component.RestitutionThreshold); Serialize.Value(writer, "RestitutionThreshold", component.RestitutionThreshold);
}); });
SerializeComponent<CircleCollider2DComponent>(writer, entity, "CircleCollider2D", scope (component) =>
{
Serialize.Value(writer, "Offset", component.Offset);
Serialize.Value(writer, "Radius", component.Radius);
Serialize.Value(writer, "Density", component.Density);
Serialize.Value(writer, "Friction", component.Friction);
Serialize.Value(writer, "Restitution", component.Restitution);
Serialize.Value(writer, "RestitutionThreshold", component.RestitutionThreshold);
});
} }
writer.EntryEnd(); writer.EntryEnd();
@@ -297,6 +309,8 @@ namespace GlitchyEngine.World
Try!(Deserialize.Value(reader, "Color", out component.Color)); Try!(Deserialize.Value(reader, "Color", out component.Color));
reader.EntryEnd(); reader.EntryEnd();
Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform)); Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform));
reader.EntryEnd();
Try!(Deserialize.Value(reader, "IsCircle", out component.IsCircle));
return .Ok; return .Ok;
})); }));
@@ -419,6 +433,24 @@ namespace GlitchyEngine.World
reader.EntryEnd(); reader.EntryEnd();
Deserialize.Value(reader, "RestitutionThreshold", out component.RestitutionThreshold); Deserialize.Value(reader, "RestitutionThreshold", out component.RestitutionThreshold);
return .Ok;
}));
case "CircleCollider2D":
Try!(DeserializeComponent<CircleCollider2DComponent>(reader, entity, scope (component) =>
{
Deserialize.Value(reader, "Offset", out component.Offset);
reader.EntryEnd();
Deserialize.Value(reader, "Radius", out component.Radius);
reader.EntryEnd();
Deserialize.Value(reader, "Density", out component.Density);
reader.EntryEnd();
Deserialize.Value(reader, "Friction", out component.Friction);
reader.EntryEnd();
Deserialize.Value(reader, "Restitution", out component.Restitution);
reader.EntryEnd();
Deserialize.Value(reader, "RestitutionThreshold", out component.RestitutionThreshold);
return .Ok; return .Ok;
})); }));