diff --git a/src/Engine.AI/AiCommandProcessor.cs b/src/Engine.AI/AiCommandProcessor.cs
index 1ee1425..1d2cb64 100644
--- a/src/Engine.AI/AiCommandProcessor.cs
+++ b/src/Engine.AI/AiCommandProcessor.cs
@@ -6,6 +6,7 @@ using Engine.AI.Commands;
using Engine.AI.Serialization;
using Engine.Core;
using Engine.Core.Components;
+using Engine.Graphics;
using Flecs.NET.Core;
namespace Engine.AI;
@@ -78,7 +79,17 @@ public sealed class AiCommandProcessor
private AiCommandResult SpawnModel(SpawnModelCommand command)
{
- var mesh = _modelLoader(command.ModelPath);
+ Mesh mesh;
+ if (command.Shape == "sphere")
+ {
+ var r = MathF.Max(MathF.Max(command.Scale.X, command.Scale.Y), command.Scale.Z) * 0.5f;
+ mesh = ProceduralMesh.CreateSphere(r, 24, 12, new Vector3(0.5f, 0.6f, 0.9f));
+ }
+ else
+ {
+ mesh = _modelLoader(command.ModelPath);
+ }
+
var entity = _world.Entity(command.Name)
.Set(new Transform(command.Position, command.Rotation, command.Scale))
.Set(mesh);
@@ -86,11 +97,17 @@ public sealed class AiCommandProcessor
if (command.Physics)
{
var maxScale = MathF.Max(MathF.Max(command.Scale.X, command.Scale.Y), command.Scale.Z);
- var rb = RigidBody.DynamicBox(new Vector3(maxScale * 0.5f), mass: maxScale * 2f);
- entity.Set(rb);
+ if (command.Shape == "sphere")
+ {
+ entity.Set(RigidBody.DynamicSphere(maxScale * 0.5f, mass: maxScale * 2f));
+ }
+ else
+ {
+ entity.Set(RigidBody.DynamicBox(new Vector3(maxScale * 0.5f), mass: maxScale * 2f));
+ }
}
- return AiCommandResult.Ok($"Spawned entity '{command.Name}' with model '{command.ModelPath}' (id {(ulong)entity.Id}).");
+ return AiCommandResult.Ok($"Spawned entity '{command.Name}' with shape '{command.Shape}' (id {(ulong)entity.Id}).");
}
private AiCommandResult SetTransform(SetTransformCommand command)
diff --git a/src/Engine.AI/Commands/SpawnModelCommand.cs b/src/Engine.AI/Commands/SpawnModelCommand.cs
index c7cc5f6..45ca3f0 100644
--- a/src/Engine.AI/Commands/SpawnModelCommand.cs
+++ b/src/Engine.AI/Commands/SpawnModelCommand.cs
@@ -13,4 +13,5 @@ public sealed record SpawnModelCommand : AiCommand
public Quaternion Rotation { get; init; } = Quaternion.Identity;
public Vector3 Scale { get; init; } = Vector3.One;
public bool Physics { get; init; } = false;
+ public string Shape { get; init; } = "cube";
}
diff --git a/src/Engine.AI/Engine.AI.csproj b/src/Engine.AI/Engine.AI.csproj
index df8a9f9..318c4dc 100644
--- a/src/Engine.AI/Engine.AI.csproj
+++ b/src/Engine.AI/Engine.AI.csproj
@@ -13,6 +13,7 @@
+
diff --git a/src/Engine.AI/Mcp/EngineMcpTools.cs b/src/Engine.AI/Mcp/EngineMcpTools.cs
index c2c151d..1e6fab8 100644
--- a/src/Engine.AI/Mcp/EngineMcpTools.cs
+++ b/src/Engine.AI/Mcp/EngineMcpTools.cs
@@ -25,7 +25,8 @@ public sealed class EngineMcpTools
[Description("Optional position as [x, y, z] (default: 0,0,0)")] IReadOnlyList? position = null,
[Description("Optional rotation as [x, y, z, w] quaternion (default: identity)")] IReadOnlyList? rotation = null,
[Description("Optional scale as [x, y, z] (default: 1,1,1)")] IReadOnlyList? scale = null,
- [Description("Optional: enable physics (default: false)")] bool physics = false)
+ [Description("Optional: enable physics (default: false)")] bool physics = false,
+ [Description("Optional: shape type 'cube' or 'sphere' (default: cube)")] string shape = "cube")
{
var cmd = new SpawnModelCommand
{
@@ -34,7 +35,8 @@ public sealed class EngineMcpTools
Position = ToVector3(position, Vector3.Zero),
Rotation = ToQuaternion(rotation, Quaternion.Identity),
Scale = ToVector3(scale, Vector3.One),
- Physics = physics
+ Physics = physics,
+ Shape = shape
};
return EnqueueAndReturnMessage(cmd);