您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
305 行
14 KiB
305 行
14 KiB
using System.Linq;
|
|
using NUnit.Framework;
|
|
using Unity.Collections;
|
|
using Unity.Mathematics;
|
|
using Unity.Transforms;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.Entities.Tests
|
|
{
|
|
[TestFixture]
|
|
public class TransformTests : ECSTestsFixture
|
|
{
|
|
unsafe bool AssertCloseEnough(float4x4 a, float4x4 b)
|
|
{
|
|
float* ap = (float*) &a.c0.x;
|
|
float* bp = (float*) &b.c0.x;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
Assert.AreEqual(expected:ap[i],actual:bp[i],delta:0.01f);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Log(float4x4 a)
|
|
{
|
|
Debug.Log($"{a.c0.x:0.000} {a.c0.y:0.000} {a.c0.z:0.000} {a.c0.w:0.000}");
|
|
Debug.Log($"{a.c1.x:0.000} {a.c1.y:0.000} {a.c1.z:0.000} {a.c1.w:0.000}");
|
|
Debug.Log($"{a.c2.x:0.000} {a.c2.y:0.000} {a.c2.z:0.000} {a.c2.w:0.000}");
|
|
Debug.Log($"{a.c3.x:0.000} {a.c3.y:0.000} {a.c3.z:0.000} {a.c3.w:0.000}");
|
|
}
|
|
|
|
[Test]
|
|
public void TRS_ChildPosition()
|
|
{
|
|
var parent = m_Manager.CreateEntity(typeof(Position), typeof(Rotation));
|
|
var child = m_Manager.CreateEntity(typeof(Position));
|
|
var attach = m_Manager.CreateEntity(typeof(Attach));
|
|
|
|
m_Manager.SetComponentData(parent, new Position {Value = new float3(0, 2, 0)});
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(1.0f, 0.0f, 0.0f), math.up())});
|
|
m_Manager.SetComponentData(child, new Position {Value = new float3(0, 0, 1)});
|
|
m_Manager.SetComponentData(attach, new Attach {Parent = parent, Child = child});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
var childWorldPosition = m_Manager.GetComponentData<LocalToWorld>(child).Value.c3;
|
|
Assert.AreEqual(expected:1.0f,actual:childWorldPosition.x,delta:0.01f);
|
|
Assert.AreEqual(expected:2.0f,actual:childWorldPosition.y,delta:0.01f);
|
|
Assert.AreEqual(expected:0.0f,actual:childWorldPosition.z,delta:0.01f);
|
|
}
|
|
|
|
[Test]
|
|
public void TRS_ParentAddedRemoved()
|
|
{
|
|
var parent = m_Manager.CreateEntity(typeof(Position), typeof(Rotation));
|
|
var child = m_Manager.CreateEntity(typeof(Position));
|
|
var attach = m_Manager.CreateEntity(typeof(Attach));
|
|
|
|
m_Manager.SetComponentData(parent, new Position {Value = new float3(0, 2, 0)});
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(1.0f, 0.0f, 0.0f), math.up())});
|
|
m_Manager.SetComponentData(child, new Position {Value = new float3(0, 0, 1)});
|
|
m_Manager.SetComponentData(attach, new Attach {Parent = parent, Child = child});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
Assert.IsTrue(m_Manager.HasComponent<Attached>(child));
|
|
Assert.IsTrue(m_Manager.HasComponent<Parent>(child));
|
|
Assert.IsFalse(m_Manager.Exists(attach));
|
|
|
|
m_Manager.DestroyEntity(parent);
|
|
m_Manager.DestroyEntity(child);
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
Assert.IsFalse(m_Manager.Exists(parent));
|
|
Assert.IsFalse(m_Manager.Exists(child));
|
|
}
|
|
|
|
[Test]
|
|
public void TRS_FreezeChild()
|
|
{
|
|
var parent = m_Manager.CreateEntity(typeof(Position), typeof(Rotation));
|
|
var child = m_Manager.CreateEntity(typeof(Position),typeof(Static));
|
|
var attach = m_Manager.CreateEntity(typeof(Attach));
|
|
|
|
m_Manager.SetComponentData(parent, new Position {Value = new float3(0, 2, 0)});
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(1.0f, 0.0f, 0.0f), math.up())});
|
|
m_Manager.SetComponentData(child, new Position {Value = new float3(0, 0, 1)});
|
|
m_Manager.SetComponentData(attach, new Attach {Parent = parent, Child = child});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(0.0f, 1.0f, 0.0f), math.up())});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
Assert.IsFalse(m_Manager.Exists(attach));
|
|
Assert.IsTrue(m_Manager.HasComponent<Frozen>(child));
|
|
|
|
var childWorldPosition = m_Manager.GetComponentData<LocalToWorld>(child).Value.c3;
|
|
Assert.AreEqual(expected:1.0f,actual:childWorldPosition.x,delta:0.01f);
|
|
Assert.AreEqual(expected:2.0f,actual:childWorldPosition.y,delta:0.01f);
|
|
Assert.AreEqual(expected:0.0f,actual:childWorldPosition.z,delta:0.01f);
|
|
|
|
m_Manager.DestroyEntity(parent);
|
|
m_Manager.DestroyEntity(child);
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
Assert.AreEqual(0, m_ManagerDebug.EntityCount);
|
|
}
|
|
|
|
[Test]
|
|
public void TRS_ParentChangesChild()
|
|
{
|
|
var parent = m_Manager.CreateEntity(typeof(Position), typeof(Rotation));
|
|
var child = m_Manager.CreateEntity(typeof(Position));
|
|
var attach = m_Manager.CreateEntity(typeof(Attach));
|
|
|
|
m_Manager.SetComponentData(parent, new Position {Value = new float3(0, 2, 0)});
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(1.0f, 0.0f, 0.0f), math.up())});
|
|
m_Manager.SetComponentData(child, new Position {Value = new float3(0, 0, 1)});
|
|
m_Manager.SetComponentData(attach, new Attach {Parent = parent, Child = child});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(0.0f, 1.0f, 0.0f), math.up())});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
var childWorldPosition = m_Manager.GetComponentData<LocalToWorld>(child).Value.c3;
|
|
Assert.AreEqual(expected:0.0f,actual:childWorldPosition.x,delta:0.01f);
|
|
Assert.AreEqual(expected:3.0f,actual:childWorldPosition.y,delta:0.01f);
|
|
Assert.AreEqual(expected:0.0f,actual:childWorldPosition.z,delta:0.01f);
|
|
}
|
|
|
|
[Test]
|
|
public void TRS_InnerDepth()
|
|
{
|
|
var parent = m_Manager.CreateEntity(typeof(Position), typeof(Rotation));
|
|
var parent2 = m_Manager.CreateEntity(typeof(Position));
|
|
var child = m_Manager.CreateEntity(typeof(Position));
|
|
var attach = m_Manager.CreateEntity(typeof(Attach));
|
|
var attach2 = m_Manager.CreateEntity(typeof(Attach));
|
|
|
|
m_Manager.SetComponentData(parent, new Position {Value = new float3(0, 2, 0)});
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(1.0f, 0.0f, 0.0f), math.up())});
|
|
m_Manager.SetComponentData(parent2, new Position {Value = new float3(0, 0, 1)});
|
|
m_Manager.SetComponentData(child, new Position {Value = new float3(0, 0, 1)});
|
|
|
|
m_Manager.SetComponentData(attach, new Attach {Parent = parent, Child = parent2});
|
|
m_Manager.SetComponentData(attach2, new Attach {Parent = parent2, Child = child});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
var parentDepth = m_Manager.GetSharedComponentData<Depth>(parent);
|
|
var parent2Depth = m_Manager.GetSharedComponentData<Depth>(parent2);
|
|
|
|
Assert.AreEqual(0,parentDepth.Value);
|
|
Assert.AreEqual(1,parent2Depth.Value);
|
|
|
|
var childWorldPosition = m_Manager.GetComponentData<LocalToWorld>(child).Value.c3;
|
|
Assert.AreEqual(expected:2.0f,actual:childWorldPosition.x,delta:0.01f);
|
|
Assert.AreEqual(expected:2.0f,actual:childWorldPosition.y,delta:0.01f);
|
|
Assert.AreEqual(expected:0.0f,actual:childWorldPosition.z,delta:0.01f);
|
|
}
|
|
|
|
[Test]
|
|
public void TRS_LocalPositions()
|
|
{
|
|
var parent = m_Manager.CreateEntity(typeof(Position), typeof(Rotation));
|
|
var parent2 = m_Manager.CreateEntity(typeof(Position));
|
|
var child = m_Manager.CreateEntity(typeof(Position));
|
|
var attach = m_Manager.CreateEntity(typeof(Attach));
|
|
var attach2 = m_Manager.CreateEntity(typeof(Attach));
|
|
|
|
m_Manager.SetComponentData(parent, new Position {Value = new float3(0, 2, 0)});
|
|
m_Manager.SetComponentData(parent, new Rotation {Value = quaternion.lookRotation(new float3(1.0f, 0.0f, 0.0f), math.up())});
|
|
m_Manager.SetComponentData(parent2, new Position {Value = new float3(0, 0, 1)});
|
|
m_Manager.SetComponentData(child, new Position {Value = new float3(0, 0, 1)});
|
|
|
|
m_Manager.SetComponentData(attach, new Attach {Parent = parent, Child = parent2});
|
|
m_Manager.SetComponentData(attach2, new Attach {Parent = parent2, Child = child});
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
var parent2LocalPosition = m_Manager.GetComponentData<LocalToParent>(parent2).Value.c3;
|
|
Assert.AreEqual(expected:0.0f,actual:parent2LocalPosition.x,delta:0.01f);
|
|
Assert.AreEqual(expected:0.0f,actual:parent2LocalPosition.y,delta:0.01f);
|
|
Assert.AreEqual(expected:1.0f,actual:parent2LocalPosition.z,delta:0.01f);
|
|
|
|
var childLocalPosition = m_Manager.GetComponentData<LocalToParent>(child).Value.c3;
|
|
Assert.AreEqual(expected:0.0f,actual:childLocalPosition.x,delta:0.01f);
|
|
Assert.AreEqual(expected:0.0f,actual:childLocalPosition.y,delta:0.01f);
|
|
Assert.AreEqual(expected:1.0f,actual:childLocalPosition.z,delta:0.01f);
|
|
}
|
|
|
|
[Test]
|
|
public void TRS_LocalPositionsHierarchy()
|
|
{
|
|
var pi = 3.14159265359f;
|
|
var rotations = new quaternion[]
|
|
{
|
|
quaternion.eulerYZX(new float3(0.125f * pi, 0.0f, 0.0f)),
|
|
quaternion.eulerYZX(new float3(0.5f * pi, 0.0f, 0.0f)),
|
|
quaternion.eulerYZX(new float3(pi, 0.0f, 0.0f)),
|
|
};
|
|
var translations = new float3[]
|
|
{
|
|
new float3(0.0f, 0.0f, 1.0f),
|
|
new float3(0.0f, 1.0f, 0.0f),
|
|
new float3(1.0f, 0.0f, 0.0f),
|
|
new float3(0.5f, 0.5f, 0.5f),
|
|
};
|
|
|
|
// 0: R:[0] T:[0]
|
|
// 1: - R:[1] T:[1]
|
|
// 2: - R:[2] T:[0]
|
|
// 3: - R:[2] T:[1]
|
|
// 4: - R:[2] T:[2]
|
|
// 5: - R:[1] T:[0]
|
|
// 6: - R:[1] T:[1]
|
|
// 7: - R:[1] T:[2]
|
|
// 8: - R:[2] T:[2]
|
|
// 9: - R:[1] T:[0]
|
|
// 10: - R:[1] T:[1]
|
|
// 11: - R:[1] T:[2]
|
|
// 12: - R:[0] T:[0]
|
|
// 13: - R:[0] T:[1]
|
|
// 14: - R:[0] T:[2]
|
|
// 15: - R:[0] T:[2]
|
|
|
|
var rotationIndices = new int[] {0, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0};
|
|
var translationIndices = new int[] {0, 1, 0, 1, 2, 0, 1, 2, 2, 0, 1, 2, 0, 1, 2, 2};
|
|
var parentIndices = new int[] {-1, 0, 1, 1, 1, 4, 4, 4, 0, 8, 8, 8, 11, 12, 13, 14};
|
|
|
|
var expectedLocalToParent = new float4x4[16];
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
var rotationIndex = rotationIndices[i];
|
|
var translationIndex = translationIndices[i];
|
|
var localToParent = new float4x4(rotations[rotationIndex], translations[translationIndex]);
|
|
expectedLocalToParent[i] = localToParent;
|
|
}
|
|
|
|
var expectedLocalToWorld = new float4x4[16];
|
|
|
|
expectedLocalToWorld[0] = expectedLocalToParent[0];
|
|
for (int i = 1; i < 16; i++)
|
|
{
|
|
var parentIndex = parentIndices[i];
|
|
expectedLocalToWorld[i] = math.mul(expectedLocalToWorld[parentIndex], expectedLocalToParent[i]);
|
|
}
|
|
|
|
var bodyArchetype = m_Manager.CreateArchetype(typeof(Position), typeof(Rotation));
|
|
var attachArchetype = m_Manager.CreateArchetype(typeof(Attach));
|
|
var bodyEntities = new NativeArray<Entity>(16, Allocator.TempJob);
|
|
var attachEntities = new NativeArray<Entity>(15, Allocator.TempJob);
|
|
|
|
m_Manager.CreateEntity(bodyArchetype, bodyEntities);
|
|
m_Manager.CreateEntity(attachArchetype, attachEntities);
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
var rotationIndex = rotationIndices[i];
|
|
var translationIndex = translationIndices[i];
|
|
var rotation = new Rotation {Value = rotations[rotationIndex]};
|
|
var position = new Position {Value = translations[translationIndex]};
|
|
|
|
m_Manager.SetComponentData(bodyEntities[i], rotation);
|
|
m_Manager.SetComponentData(bodyEntities[i], position);
|
|
}
|
|
|
|
for (int i = 1; i < 16; i++)
|
|
{
|
|
var parentIndex = parentIndices[i];
|
|
m_Manager.SetComponentData(attachEntities[i - 1],
|
|
new Attach {Parent = bodyEntities[parentIndex], Child = bodyEntities[i]});
|
|
}
|
|
|
|
World.GetOrCreateManager<EndFrameTransformSystem>().Update();
|
|
|
|
// Check all non-root LocalToParent
|
|
for (int i = 1; i < 16; i++)
|
|
{
|
|
var entity = bodyEntities[i];
|
|
var localToParent = m_Manager.GetComponentData<LocalToParent>(entity).Value;
|
|
|
|
AssertCloseEnough(expectedLocalToParent[i], localToParent);
|
|
}
|
|
|
|
// Check all LocalToWorld
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
var entity = bodyEntities[i];
|
|
var localToWorld = m_Manager.GetComponentData<LocalToWorld>(entity).Value;
|
|
|
|
AssertCloseEnough(expectedLocalToWorld[i], localToWorld);
|
|
}
|
|
|
|
bodyEntities.Dispose();
|
|
attachEntities.Dispose();
|
|
}
|
|
}
|
|
}
|