Spatial Components
The KeenEyes.Common library provides common 3D spatial components using System.Numerics for SIMD-accelerated math operations.
Note: Transform3D was moved from
KeenEyes.SpatialtoKeenEyes.Commonto avoid forcing dependencies on spatial partitioning features. Update your using statements tousing KeenEyes.Common;.
Transform3D
The primary component for 3D positioning, rotation, and scaling:
using KeenEyes.Common;
using System.Numerics;
// Create with explicit values
var transform = new Transform3D(
position: new Vector3(10, 5, 0),
rotation: Quaternion.Identity,
scale: Vector3.One
);
// Use identity (origin, no rotation, unit scale)
var transform = Transform3D.Identity;
Properties
public struct Transform3D : IComponent
{
public Vector3 Position; // World position
public Quaternion Rotation; // Rotation as quaternion
public Vector3 Scale; // Scale factors
}
Direction Vectors
Get orientation-relative direction vectors:
ref var transform = ref world.Get<Transform3D>(entity);
Vector3 forward = transform.Forward; // -Z axis after rotation
Vector3 right = transform.Right; // +X axis after rotation
Vector3 up = transform.Up; // +Y axis after rotation
Transformation Matrix
Compute the 4x4 world matrix (Scale * Rotation * Translation):
Matrix4x4 worldMatrix = transform.ToMatrix();
Usage with ECS
Entity Creation
using KeenEyes;
using KeenEyes.Common;
var entity = world.Spawn()
.With(new Transform3D(
new Vector3(0, 0, 0),
Quaternion.Identity,
Vector3.One))
.Build();
Movement System
public class MovementSystem : SystemBase
{
public override void Update(float deltaTime)
{
foreach (var entity in World.Query<Transform3D, Velocity>())
{
ref var transform = ref World.Get<Transform3D>(entity);
ref readonly var velocity = ref World.Get<Velocity>(entity);
transform.Position += velocity.Value * deltaTime;
}
}
}
Rotation
// Rotate around Y axis
ref var transform = ref world.Get<Transform3D>(entity);
transform.Rotation *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, angle);
// Look at a target
var direction = Vector3.Normalize(target - transform.Position);
transform.Rotation = Quaternion.CreateFromRotationMatrix(
Matrix4x4.CreateLookAt(Vector3.Zero, direction, Vector3.UnitY));
// Euler angles (yaw, pitch, roll)
transform.Rotation = Quaternion.CreateFromYawPitchRoll(yaw, pitch, roll);
Scaling
ref var transform = ref world.Get<Transform3D>(entity);
// Uniform scale
transform.Scale = new Vector3(2, 2, 2);
// Non-uniform scale
transform.Scale = new Vector3(1, 2, 0.5f);
Integration with Graphics
Transform3D is used by the graphics plugin for positioning cameras, lights, and renderables:
using KeenEyes.Graphics;
using KeenEyes.Common;
// Camera with transform
world.Spawn()
.With(new Transform3D(new Vector3(0, 5, 10), Quaternion.Identity, Vector3.One))
.With(Camera.CreatePerspective(60f, 16f/9f, 0.1f, 1000f))
.WithTag<MainCameraTag>()
.Build();
// Renderable object with transform
world.Spawn()
.With(Transform3D.Identity)
.With(new Renderable(meshId, 0))
.With(Material.Default)
.Build();
// Light with transform (direction from rotation)
world.Spawn()
.With(new Transform3D(Vector3.Zero,
Quaternion.CreateFromYawPitchRoll(0, -0.5f, 0), Vector3.One))
.With(Light.Directional(new Vector3(1, 1, 1), 1f))
.Build();
Performance Notes
- Uses
System.Numericstypes for SIMD acceleration ToMatrix()computes the matrix on-demand (not cached)- For hot paths accessing only position, consider separate
PositionandRotationcomponents
Component Splitting
If you frequently access only subsets of transform data, consider splitting:
// Separate components for cache efficiency
public struct Position3D : IComponent
{
public Vector3 Value;
}
public struct Rotation3D : IComponent
{
public Quaternion Value;
}
public struct Scale3D : IComponent
{
public Vector3 Value;
}
// Query only what you need
foreach (var entity in world.Query<Position3D, Velocity>())
{
// Only Position3D and Velocity in cache
}
System.Numerics Types
Transform3D uses these SIMD-accelerated types:
| Type | Description |
|---|---|
Vector3 |
3D position/direction/scale |
Quaternion |
Rotation (avoids gimbal lock) |
Matrix4x4 |
4x4 transformation matrix |
Common operations:
// Vector math
var sum = v1 + v2;
var scaled = v * 2f;
var normalized = Vector3.Normalize(v);
var dot = Vector3.Dot(v1, v2);
var cross = Vector3.Cross(v1, v2);
var distance = Vector3.Distance(a, b);
var lerped = Vector3.Lerp(a, b, t);
// Quaternion operations
var combined = q1 * q2;
var inverted = Quaternion.Inverse(q);
var slerped = Quaternion.Slerp(a, b, t);
var fromAxis = Quaternion.CreateFromAxisAngle(axis, angle);
var fromEuler = Quaternion.CreateFromYawPitchRoll(yaw, pitch, roll);
// Transform a point by rotation
var rotated = Vector3.Transform(point, rotation);