Refactor engine to support double-precision vectors

This commit is contained in:
Wojtek Figat
2022-06-13 00:40:32 +02:00
parent f82e370392
commit a881c90b2e
744 changed files with 19062 additions and 12467 deletions

View File

@@ -26,8 +26,7 @@ void MeshAccelerationStructure::BuildBVH(int32 node, int32 maxLeafSize, Array<by
right.Leaf.MeshIndex = root.Leaf.MeshIndex;
// Mid-point splitting based on the largest axis
Vector3 boundsSize;
root.Bounds.GetSize(boundsSize);
const Float3 boundsSize = root.Bounds.GetSize();
int32 axisCount = 0;
int32 axis = 0;
RETRY:
@@ -51,9 +50,9 @@ RETRY:
// Go to the next axis
axis = (axis + 1) % 3;
}
const float midPoint = root.Bounds.Minimum.Raw[axis] + boundsSize.Raw[axis] * 0.5f;
const float midPoint = (float)(root.Bounds.Minimum.Raw[axis] + boundsSize.Raw[axis] * 0.5f);
const Mesh& meshData = _meshes[root.Leaf.MeshIndex];
const Vector3* vb = meshData.VertexBuffer.Get<Vector3>();
const Float3* vb = meshData.VertexBuffer.Get<Float3>();
int32 indexStart = root.Leaf.TriangleIndex * 3;
int32 indexEnd = indexStart + root.Leaf.TriangleCount * 3;
left.Leaf.TriangleCount = 0;
@@ -152,7 +151,7 @@ RETRY:
BuildBVH(childIndex + 1, maxLeafSize, scratch);
}
bool MeshAccelerationStructure::PointQueryBVH(int32 node, const Vector3& point, float& hitDistance, Vector3& hitPoint, Triangle& hitTriangle) const
bool MeshAccelerationStructure::PointQueryBVH(int32 node, const Vector3& point, Real& hitDistance, Vector3& hitPoint, Triangle& hitTriangle) const
{
const auto& root = _bvh[node];
bool hit = false;
@@ -161,7 +160,7 @@ bool MeshAccelerationStructure::PointQueryBVH(int32 node, const Vector3& point,
// Find closest triangle
Vector3 p;
const Mesh& meshData = _meshes[root.Leaf.MeshIndex];
const Vector3* vb = meshData.VertexBuffer.Get<Vector3>();
const Float3* vb = meshData.VertexBuffer.Get<Float3>();
const int32 indexStart = root.Leaf.TriangleIndex * 3;
const int32 indexEnd = indexStart + root.Leaf.TriangleCount * 3;
if (meshData.Use16BitIndexBuffer)
@@ -173,7 +172,7 @@ bool MeshAccelerationStructure::PointQueryBVH(int32 node, const Vector3& point,
Vector3 v1 = vb[ib16[i++]];
Vector3 v2 = vb[ib16[i++]];
CollisionsHelper::ClosestPointPointTriangle(point, v0, v1, v2, p);
const float distance = Vector3::Distance(point, p);
const Real distance = Vector3::Distance(point, p);
if (distance < hitDistance)
{
hitDistance = distance;
@@ -192,7 +191,7 @@ bool MeshAccelerationStructure::PointQueryBVH(int32 node, const Vector3& point,
Vector3 v1 = vb[ib32[i++]];
Vector3 v2 = vb[ib32[i++]];
CollisionsHelper::ClosestPointPointTriangle(point, v0, v1, v2, p);
const float distance = Vector3::Distance(point, p);
const Real distance = Vector3::Distance(point, p);
if (distance < hitDistance)
{
hitDistance = distance;
@@ -218,19 +217,19 @@ bool MeshAccelerationStructure::PointQueryBVH(int32 node, const Vector3& point,
return hit;
}
bool MeshAccelerationStructure::RayCastBVH(int32 node, const Ray& ray, float& hitDistance, Vector3& hitNormal, Triangle& hitTriangle) const
bool MeshAccelerationStructure::RayCastBVH(int32 node, const Ray& ray, Real& hitDistance, Vector3& hitNormal, Triangle& hitTriangle) const
{
const auto& root = _bvh[node];
if (!root.Bounds.Intersects(ray))
return false;
Vector3 normal;
float distance;
Real distance;
bool hit = false;
if (root.Leaf.IsLeaf)
{
// Ray cast along triangles in the leaf
const Mesh& meshData = _meshes[root.Leaf.MeshIndex];
const Vector3* vb = meshData.VertexBuffer.Get<Vector3>();
const Float3* vb = meshData.VertexBuffer.Get<Float3>();
const int32 indexStart = root.Leaf.TriangleIndex * 3;
const int32 indexEnd = indexStart + root.Leaf.TriangleCount * 3;
if (meshData.Use16BitIndexBuffer)
@@ -343,28 +342,28 @@ void MeshAccelerationStructure::Add(ModelData* modelData, int32 lodIndex, bool c
if (copy)
{
meshData.IndexBuffer.Copy((const byte*)mesh->Indices.Get(), meshData.Indices * sizeof(uint32));
meshData.VertexBuffer.Copy((const byte*)mesh->Positions.Get(), meshData.Vertices * sizeof(Vector3));
meshData.VertexBuffer.Copy((const byte*)mesh->Positions.Get(), meshData.Vertices * sizeof(Float3));
}
else
{
meshData.IndexBuffer.Link((const byte*)mesh->Indices.Get(), meshData.Indices * sizeof(uint32));
meshData.VertexBuffer.Link((const byte*)mesh->Positions.Get(), meshData.Vertices * sizeof(Vector3));
meshData.VertexBuffer.Link((const byte*)mesh->Positions.Get(), meshData.Vertices * sizeof(Float3));
}
meshData.Use16BitIndexBuffer = false;
mesh->CalculateBox(meshData.Bounds);
}
}
void MeshAccelerationStructure::Add(Vector3* vb, int32 vertices, void* ib, int32 indices, bool use16BitIndex, bool copy)
void MeshAccelerationStructure::Add(Float3* vb, int32 vertices, void* ib, int32 indices, bool use16BitIndex, bool copy)
{
auto& meshData = _meshes.AddOne();
if (copy)
{
meshData.VertexBuffer.Copy((const byte*)vb, vertices * sizeof(Vector3));
meshData.VertexBuffer.Copy((const byte*)vb, vertices * sizeof(Float3));
}
else
{
meshData.VertexBuffer.Link((const byte*)vb, vertices * sizeof(Vector3));
meshData.VertexBuffer.Link((const byte*)vb, vertices * sizeof(Float3));
}
meshData.IndexBuffer.Copy((const byte*)ib, indices * (use16BitIndex ? sizeof(uint16) : sizeof(uint32)));
meshData.Vertices = vertices;
@@ -409,9 +408,9 @@ void MeshAccelerationStructure::BuildBVH(int32 maxLeafSize)
BuildBVH(i + 1, maxLeafSize, scratch);
}
bool MeshAccelerationStructure::PointQuery(const Vector3& point, float& hitDistance, Vector3& hitPoint, Triangle& hitTriangle, float maxDistance) const
bool MeshAccelerationStructure::PointQuery(const Vector3& point, Real& hitDistance, Vector3& hitPoint, Triangle& hitTriangle, Real maxDistance) const
{
hitDistance = maxDistance >= MAX_float ? maxDistance : maxDistance * maxDistance;
hitDistance = maxDistance >= MAX_Real ? maxDistance : maxDistance * maxDistance;
bool hit = false;
// BVH
@@ -449,7 +448,7 @@ bool MeshAccelerationStructure::PointQuery(const Vector3& point, float& hitDista
Vector3 p;
for (const Mesh& meshData : _meshes)
{
const Vector3* vb = meshData.VertexBuffer.Get<Vector3>();
const Float3* vb = meshData.VertexBuffer.Get<Float3>();
if (meshData.Use16BitIndexBuffer)
{
const uint16* ib16 = meshData.IndexBuffer.Get<uint16>();
@@ -459,7 +458,7 @@ bool MeshAccelerationStructure::PointQuery(const Vector3& point, float& hitDista
Vector3 v1 = vb[ib16[i++]];
Vector3 v2 = vb[ib16[i++]];
CollisionsHelper::ClosestPointPointTriangle(point, v0, v1, v2, p);
const float distance = Vector3::DistanceSquared(point, p);
const Real distance = Vector3::DistanceSquared(point, p);
if (distance < hitDistance)
{
hitDistance = distance;
@@ -478,7 +477,7 @@ bool MeshAccelerationStructure::PointQuery(const Vector3& point, float& hitDista
Vector3 v1 = vb[ib32[i++]];
Vector3 v2 = vb[ib32[i++]];
CollisionsHelper::ClosestPointPointTriangle(point, v0, v1, v2, p);
const float distance = Vector3::DistanceSquared(point, p);
const Real distance = Vector3::DistanceSquared(point, p);
if (distance < hitDistance)
{
hitDistance = distance;
@@ -495,7 +494,7 @@ bool MeshAccelerationStructure::PointQuery(const Vector3& point, float& hitDista
}
}
bool MeshAccelerationStructure::RayCast(const Ray& ray, float& hitDistance, Vector3& hitNormal, Triangle& hitTriangle, float maxDistance) const
bool MeshAccelerationStructure::RayCast(const Ray& ray, Real& hitDistance, Vector3& hitNormal, Triangle& hitTriangle, Real maxDistance) const
{
hitDistance = maxDistance;
@@ -508,13 +507,13 @@ bool MeshAccelerationStructure::RayCast(const Ray& ray, float& hitDistance, Vect
// Brute-force
{
Vector3 normal;
float distance;
Real distance;
bool hit = false;
for (const Mesh& meshData : _meshes)
{
if (!meshData.Bounds.Intersects(ray))
continue;
const Vector3* vb = meshData.VertexBuffer.Get<Vector3>();
const Float3* vb = meshData.VertexBuffer.Get<Float3>();
if (meshData.Use16BitIndexBuffer)
{
const uint16* ib16 = meshData.IndexBuffer.Get<uint16>();

View File

@@ -53,8 +53,8 @@ private:
Array<BVH> _bvh;
void BuildBVH(int32 node, int32 maxLeafSize, Array<byte>& scratch);
bool PointQueryBVH(int32 node, const Vector3& point, float& hitDistance, Vector3& hitPoint, Triangle& hitTriangle) const;
bool RayCastBVH(int32 node, const Ray& ray, float& hitDistance, Vector3& hitNormal, Triangle& hitTriangle) const;
bool PointQueryBVH(int32 node, const Vector3& point, Real& hitDistance, Vector3& hitPoint, Triangle& hitTriangle) const;
bool RayCastBVH(int32 node, const Ray& ray, Real& hitDistance, Vector3& hitNormal, Triangle& hitTriangle) const;
public:
// Adds the model geometry for the build to the structure.
@@ -64,16 +64,16 @@ public:
void Add(ModelData* modelData, int32 lodIndex, bool copy = false);
// Adds the triangles geometry for the build to the structure.
void Add(Vector3* vb, int32 vertices, void* ib, int32 indices, bool use16BitIndex, bool copy = false);
void Add(Float3* vb, int32 vertices, void* ib, int32 indices, bool use16BitIndex, bool copy = false);
// Builds Bounding Volume Hierarchy (BVH) structure for accelerated geometry queries.
void BuildBVH(int32 maxLeafSize = 16);
// Queries the closest triangle.
bool PointQuery(const Vector3& point, float& hitDistance, Vector3& hitPoint, Triangle& hitTriangle, float maxDistance = MAX_float) const;
bool PointQuery(const Vector3& point, Real& hitDistance, Vector3& hitPoint, Triangle& hitTriangle, Real maxDistance = MAX_Real) const;
// Ray traces the triangles.
bool RayCast(const Ray& ray, float& hitDistance, Vector3& hitNormal, Triangle& hitTriangle, float maxDistance = MAX_float) const;
bool RayCast(const Ray& ray, Real& hitDistance, Vector3& hitNormal, Triangle& hitTriangle, Real maxDistance = MAX_Real) const;
};
#endif

View File

@@ -47,19 +47,19 @@ public:
}
};
Vector2 ToVector2(const aiVector2D& v)
Float2 ToFloat2(const aiVector2D& v)
{
return Vector2(v.x, v.y);
return Float2(v.x, v.y);
}
Vector2 ToVector2(const aiVector3D& v)
Float2 ToFloat2(const aiVector3D& v)
{
return Vector2(v.x, v.y);
return Float2(v.x, v.y);
}
Vector3 ToVector3(const aiVector3D& v)
Float3 ToFloat3(const aiVector3D& v)
{
return Vector3(v.x, v.y, v.z);
return Float3(v.x, v.y, v.z);
}
Color ToColor(const aiColor3D& v)
@@ -234,7 +234,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
mesh.MaterialSlotIndex = aMesh->mMaterialIndex;
// Vertex positions
mesh.Positions.Set((const Vector3*)aMesh->mVertices, aMesh->mNumVertices);
mesh.Positions.Set((const Float3*)aMesh->mVertices, aMesh->mNumVertices);
// Texture coordinates
if (aMesh->mTextureCoords[0])
@@ -243,7 +243,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
aiVector3D* a = aMesh->mTextureCoords[0];
for (uint32 v = 0; v < aMesh->mNumVertices; v++)
{
mesh.UVs[v] = *(Vector2*)a;
mesh.UVs[v] = *(Float2*)a;
a++;
}
}
@@ -251,13 +251,13 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
// Normals
if (aMesh->mNormals)
{
mesh.Normals.Set((const Vector3*)aMesh->mNormals, aMesh->mNumVertices);
mesh.Normals.Set((const Float3*)aMesh->mNormals, aMesh->mNumVertices);
}
// Tangents
if (aMesh->mTangents)
{
mesh.Tangents.Set((const Vector3*)aMesh->mTangents, aMesh->mNumVertices);
mesh.Tangents.Set((const Float3*)aMesh->mTangents, aMesh->mNumVertices);
}
// Indices
@@ -320,7 +320,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
aiVector3D* a = aMesh->mTextureCoords[inputChannelIndex];
for (uint32 v = 0; v < aMesh->mNumVertices; v++)
{
mesh.LightmapUVs[v] = *(Vector2*)a;
mesh.LightmapUVs[v] = *(Float2*)a;
a++;
}
}
@@ -349,7 +349,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
mesh.BlendIndices.Resize(vertexCount);
mesh.BlendWeights.Resize(vertexCount);
mesh.BlendIndices.SetAll(Int4::Zero);
mesh.BlendWeights.SetAll(Vector4::Zero);
mesh.BlendWeights.SetAll(Float4::Zero);
// Build skinning clusters and fill controls points data structure
for (unsigned boneId = 0; boneId < aMesh->mNumBones; boneId++)
@@ -444,24 +444,24 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
if (shapeVertices)
{
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
blendShapeData.Vertices[i].PositionDelta = ToVector3(shapeVertices[i]) - mesh.Positions[i];
blendShapeData.Vertices[i].PositionDelta = ToFloat3(shapeVertices[i]) - mesh.Positions[i];
}
else
{
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
blendShapeData.Vertices[i].PositionDelta = Vector3::Zero;
blendShapeData.Vertices[i].PositionDelta = Float3::Zero;
}
const aiVector3D* shapeNormals = aAnimMesh->mNormals;
if (shapeNormals)
{
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
blendShapeData.Vertices[i].NormalDelta = ToVector3(shapeNormals[i]) - mesh.Normals[i];
blendShapeData.Vertices[i].NormalDelta = ToFloat3(shapeNormals[i]) - mesh.Normals[i];
}
else
{
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
blendShapeData.Vertices[i].NormalDelta = Vector3::Zero;
blendShapeData.Vertices[i].NormalDelta = Float3::Zero;
}
}
}
@@ -587,7 +587,7 @@ bool ImportMesh(int32 i, ImportedModelData& result, AssimpImporterData& data, St
return false;
}
void ImportCurve(aiVectorKey* keys, uint32 keysCount, LinearCurve<Vector3>& curve)
void ImportCurve(aiVectorKey* keys, uint32 keysCount, LinearCurve<Float3>& curve)
{
if (keys == nullptr || keysCount == 0)
return;
@@ -600,7 +600,7 @@ void ImportCurve(aiVectorKey* keys, uint32 keysCount, LinearCurve<Vector3>& curv
auto& key = keyframes[i];
key.Time = (float)aKey.mTime;
key.Value = ToVector3(aKey.mValue);
key.Value = ToFloat3(aKey.mValue);
}
}

View File

@@ -49,36 +49,32 @@ Matrix ToFlaxType(const FbxAMatrix& value)
for (int32 row = 0; row < 4; row++)
for (int32 col = 0; col < 4; col++)
native.Values[row][col] = (float)value[col][row];
return native;
}
Vector3 ToFlaxType(const FbxVector4& value)
Float3 ToFlaxType(const FbxVector4& value)
{
Vector3 native;
Float3 native;
native.X = (float)value[0];
native.Y = (float)value[1];
native.Z = (float)value[2];
return native;
}
Vector3 ToFlaxType(const FbxDouble3& value)
Float3 ToFlaxType(const FbxDouble3& value)
{
Vector3 native;
Float3 native;
native.X = (float)value[0];
native.Y = (float)value[1];
native.Z = (float)value[2];
return native;
}
Vector2 ToFlaxType(const FbxVector2& value)
Float2 ToFlaxType(const FbxVector2& value)
{
Vector2 native;
Float2 native;
native.X = (float)value[0];
native.Y = 1 - (float)value[1];
return native;
}
@@ -89,7 +85,6 @@ Color ToFlaxType(const FbxColor& value)
native.G = (float)value[1];
native.B = (float)value[2];
native.A = (float)value[3];
return native;
}
@@ -218,9 +213,9 @@ void ProcessNodes(ImporterData& data, FbxNode* fbxNode, int32 parentIndex)
{
const int32 nodeIndex = data.Nodes.Count();
Vector3 translation = ToFlaxType(fbxNode->EvaluateLocalTranslation(FbxTime(0)));
Vector3 rotationEuler = ToFlaxType(fbxNode->EvaluateLocalRotation(FbxTime(0)));
Vector3 scale = ToFlaxType(fbxNode->EvaluateLocalScaling(FbxTime(0)));
Float3 translation = ToFlaxType(fbxNode->EvaluateLocalTranslation(FbxTime(0)));
Float3 rotationEuler = ToFlaxType(fbxNode->EvaluateLocalRotation(FbxTime(0)));
Float3 scale = ToFlaxType(fbxNode->EvaluateLocalScaling(FbxTime(0)));
Quaternion rotation = Quaternion::Euler(rotationEuler);
// Create node
@@ -231,9 +226,9 @@ void ProcessNodes(ImporterData& data, FbxNode* fbxNode, int32 parentIndex)
node.FbxNode = fbxNode;
// Geometry transform is applied to geometry (mesh data) only, it is not inherited by children, so we store it separately
Vector3 geomTrans = ToFlaxType(fbxNode->GeometricTranslation.Get());
Vector3 geomRotEuler = ToFlaxType(fbxNode->GeometricRotation.Get());
Vector3 geomScale = ToFlaxType(fbxNode->GeometricScaling.Get());
Float3 geomTrans = ToFlaxType(fbxNode->GeometricTranslation.Get());
Float3 geomRotEuler = ToFlaxType(fbxNode->GeometricRotation.Get());
Float3 geomScale = ToFlaxType(fbxNode->GeometricScaling.Get());
Quaternion geomRotation = Quaternion::Euler(geomRotEuler);
Transform(geomTrans, geomRotation, geomScale).GetWorld(node.GeomTransform);
@@ -473,7 +468,7 @@ bool ProcessMesh(ImporterData& data, FbxMesh* fbxMesh, MeshData& mesh, String& e
mesh.BlendIndices.Resize(vertexCount);
mesh.BlendWeights.Resize(vertexCount);
mesh.BlendIndices.SetAll(Int4::Zero);
mesh.BlendWeights.SetAll(Vector4::Zero);
mesh.BlendWeights.SetAll(Float4::Zero);
for (int deformerIndex = 0; deformerIndex < skinDeformerCount; deformerIndex++)
{
@@ -608,7 +603,7 @@ bool ProcessMesh(ImporterData& data, FbxMesh* fbxMesh, MeshData& mesh, String& e
blendShapeData.Vertices[i].PositionDelta = ToFlaxType(shapeControlPoints[i] - controlPoints[i]);
// TODO: support importing normals from blend shape
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
blendShapeData.Vertices[i].NormalDelta = Vector3::Zero;
blendShapeData.Vertices[i].NormalDelta = Float3::Zero;
}
}
}
@@ -730,7 +725,7 @@ bool ImportMeshes(ImporterData& data, String& errorMsg)
}
/*
void ImportCurve(aiVectorKey* keys, uint32 keysCount, LinearCurve<Vector3>& curve)
void ImportCurve(aiVectorKey* keys, uint32 keysCount, LinearCurve<Float3>& curve)
{
if (keys == nullptr || keysCount == 0)
return;
@@ -743,7 +738,7 @@ void ImportCurve(aiVectorKey* keys, uint32 keysCount, LinearCurve<Vector3>& curv
auto& key = keyframes[i];
key.Time = (float)aKey.mTime;
key.Value = ToVector3(aKey.mValue);
key.Value = ToFlaxType(aKey.mValue);
}
}

View File

@@ -17,19 +17,19 @@
#include <ThirdParty/OpenFBX/ofbx.h>
#include <memory>
Vector2 ToVector2(const ofbx::Vec2& v)
Float2 ToFloat2(const ofbx::Vec2& v)
{
return Vector2((float)v.x, (float)v.y);
return Float2((float)v.x, (float)v.y);
}
Vector2 ToVector2(const ofbx::Vec3& v)
Float2 ToFloat2(const ofbx::Vec3& v)
{
return Vector2((float)v.x, (float)v.y);
return Float2((float)v.x, (float)v.y);
}
Vector3 ToVector3(const ofbx::Vec3& v)
Float3 ToFloat3(const ofbx::Vec3& v)
{
return Vector3((float)v.x, (float)v.y, (float)v.z);
return Float3((float)v.x, (float)v.y, (float)v.z);
}
Color ToColor(const ofbx::Vec4& v)
@@ -85,9 +85,9 @@ struct OpenFbxImporterData
const ModelTool::Options& Options;
ofbx::GlobalSettings GlobalSettings;
Vector3 Up;
Vector3 Front;
Vector3 Right;
Float3 Up;
Float3 Front;
Float3 Right;
bool ConvertRH;
float FrameRate;
Quaternion RootConvertRotation = Quaternion::Identity;
@@ -118,52 +118,52 @@ struct OpenFbxImporterData
switch (GlobalSettings.UpAxis)
{
case ofbx::UpVector_AxisX:
Up = Vector3((float)GlobalSettings.UpAxisSign, 0, 0);
Up = Float3((float)GlobalSettings.UpAxisSign, 0, 0);
switch (GlobalSettings.FrontAxis)
{
case ofbx::FrontVector_ParityEven:
// Up: X, Front: Y, Right: Z
Front = Vector3(0, (float)GlobalSettings.FrontAxisSign, 0);
Right = Vector3(0, 0, coordAxisSign);
Front = Float3(0, (float)GlobalSettings.FrontAxisSign, 0);
Right = Float3(0, 0, coordAxisSign);
break;
case ofbx::FrontVector_ParityOdd:
// Up: X, Front: Z, Right: Y
Front = Vector3(0, 0, (float)GlobalSettings.FrontAxisSign);
Right = Vector3(0, coordAxisSign, 0);
Front = Float3(0, 0, (float)GlobalSettings.FrontAxisSign);
Right = Float3(0, coordAxisSign, 0);
break;
default: ;
}
break;
case ofbx::UpVector_AxisY:
Up = Vector3(0, (float)GlobalSettings.UpAxisSign, 0);
Up = Float3(0, (float)GlobalSettings.UpAxisSign, 0);
switch (GlobalSettings.FrontAxis)
{
case ofbx::FrontVector_ParityEven:
// Up: Y, Front: X, Right: Z
Front = Vector3((float)GlobalSettings.FrontAxisSign, 0, 0);
Right = Vector3(0, 0, coordAxisSign);
Front = Float3((float)GlobalSettings.FrontAxisSign, 0, 0);
Right = Float3(0, 0, coordAxisSign);
break;
case ofbx::FrontVector_ParityOdd:
// Up: Y, Front: Z, Right: X
Front = Vector3(0, 0, (float)GlobalSettings.FrontAxisSign);
Right = Vector3(coordAxisSign, 0, 0);
Front = Float3(0, 0, (float)GlobalSettings.FrontAxisSign);
Right = Float3(coordAxisSign, 0, 0);
break;
default: ;
}
break;
case ofbx::UpVector_AxisZ:
Up = Vector3(0, 0, (float)GlobalSettings.UpAxisSign);
Up = Float3(0, 0, (float)GlobalSettings.UpAxisSign);
switch (GlobalSettings.FrontAxis)
{
case ofbx::FrontVector_ParityEven:
// Up: Z, Front: X, Right: Y
Front = Vector3((float)GlobalSettings.FrontAxisSign, 0, 0);
Right = Vector3(0, coordAxisSign, 0);
Front = Float3((float)GlobalSettings.FrontAxisSign, 0, 0);
Right = Float3(0, coordAxisSign, 0);
break;
case ofbx::FrontVector_ParityOdd:
// Up: Z, Front: Y, Right: X
Front = Vector3((float)GlobalSettings.FrontAxisSign, 0, 0);
Right = Vector3(coordAxisSign, 0, 0);
Front = Float3((float)GlobalSettings.FrontAxisSign, 0, 0);
Right = Float3(coordAxisSign, 0, 0);
break;
default: ;
}
@@ -491,7 +491,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
mesh.Positions.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
{
mesh.Positions.Get()[i] = ToVector3(vertices[i + firstVertexOffset]);
mesh.Positions.Get()[i] = ToFloat3(vertices[i + firstVertexOffset]);
}
// Indices (dummy index buffer)
@@ -512,7 +512,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
mesh.UVs.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
{
mesh.UVs.Get()[i] = ToVector2(uvs[i + firstVertexOffset]);
mesh.UVs.Get()[i] = ToFloat2(uvs[i + firstVertexOffset]);
}
if (data.ConvertRH)
{
@@ -537,7 +537,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
mesh.Normals.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
{
mesh.Normals.Get()[i] = ToVector3(normals[i + firstVertexOffset]);
mesh.Normals.Get()[i] = ToFloat3(normals[i + firstVertexOffset]);
}
if (data.ConvertRH)
{
@@ -559,7 +559,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
mesh.Tangents.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
{
mesh.Tangents.Get()[i] = ToVector3(tangents[i + firstVertexOffset]);
mesh.Tangents.Get()[i] = ToFloat3(tangents[i + firstVertexOffset]);
}
if (data.ConvertRH)
{
@@ -614,7 +614,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
mesh.LightmapUVs.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
{
mesh.LightmapUVs.Get()[i] = ToVector2(lightmapUVs[i + firstVertexOffset]);
mesh.LightmapUVs.Get()[i] = ToFloat2(lightmapUVs[i + firstVertexOffset]);
}
if (data.ConvertRH)
{
@@ -646,7 +646,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
mesh.BlendIndices.Resize(vertexCount);
mesh.BlendWeights.Resize(vertexCount);
mesh.BlendIndices.SetAll(Int4::Zero);
mesh.BlendWeights.SetAll(Vector4::Zero);
mesh.BlendWeights.SetAll(Float4::Zero);
for (int clusterIndex = 0, c = skin->getClusterCount(); clusterIndex < c; clusterIndex++)
{
@@ -737,18 +737,18 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
auto shapeVertices = shape->getVertices();
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
{
auto delta = ToVector3(shapeVertices[i + firstVertexOffset]) - mesh.Positions.Get()[i];
auto delta = ToFloat3(shapeVertices[i + firstVertexOffset]) - mesh.Positions.Get()[i];
blendShapeData.Vertices.Get()[i].PositionDelta = delta;
}
auto shapeNormals = shape->getNormals();
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
{
/*auto delta = ToVector3(shapeNormals[i + firstVertexOffset]) - mesh.Normals[i];
/*auto delta = ToFloat3(shapeNormals[i + firstVertexOffset]) - mesh.Normals[i];
auto length = delta.Length();
if (length > ZeroTolerance)
delta /= length;*/
auto delta = Vector3::Zero; // TODO: blend shape normals deltas fix when importing from fbx
auto delta = Float3::Zero; // TODO: blend shape normals deltas fix when importing from fbx
blendShapeData.Vertices.Get()[i].NormalDelta = delta;
}
}
@@ -917,7 +917,7 @@ struct Frame
ofbx::Vec3 Scaling;
};
void ExtractKeyframePosition(const ofbx::Object* bone, ofbx::Vec3& trans, const Frame& localFrame, Vector3& keyframe)
void ExtractKeyframePosition(const ofbx::Object* bone, ofbx::Vec3& trans, const Frame& localFrame, Float3& keyframe)
{
const Matrix frameTrans = ToMatrix(bone->evalLocal(trans, localFrame.Rotation, localFrame.Scaling));
keyframe = frameTrans.GetTranslation();
@@ -929,7 +929,7 @@ void ExtractKeyframeRotation(const ofbx::Object* bone, ofbx::Vec3& trans, const
Quaternion::RotationMatrix(frameTrans, keyframe);
}
void ExtractKeyframeScale(const ofbx::Object* bone, ofbx::Vec3& trans, const Frame& localFrame, Vector3& keyframe)
void ExtractKeyframeScale(const ofbx::Object* bone, ofbx::Vec3& trans, const Frame& localFrame, Float3& keyframe)
{
// Fix empty scale case
if (Math::IsZero(trans.x) && Math::IsZero(trans.y) && Math::IsZero(trans.z))
@@ -1045,7 +1045,7 @@ bool ImportAnimation(int32 index, ImportedModelData& data, OpenFbxImporterData&
return false;
}
static Vector3 FbxVectorFromAxisAndSign(int axis, int sign)
static Float3 FbxVectorFromAxisAndSign(int axis, int sign)
{
switch (axis)
{
@@ -1131,20 +1131,20 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
}
// Transform nodes to match the engine coordinates system - DirectX (UpVector = +Y, FrontVector = +Z, CoordSystem = -X (LeftHanded))
if (context->Up == Vector3(1, 0, 0) && context->Front == Vector3(0, 0, 1) && context->Right == Vector3(0, 1, 0))
if (context->Up == Float3(1, 0, 0) && context->Front == Float3(0, 0, 1) && context->Right == Float3(0, 1, 0))
{
context->RootConvertRotation = Quaternion::Euler(0, 180, 0);
}
else if (context->Up == Vector3(0, 1, 0) && context->Front == Vector3(-1, 0, 0) && context->Right == Vector3(0, 0, 1))
else if (context->Up == Float3(0, 1, 0) && context->Front == Float3(-1, 0, 0) && context->Right == Float3(0, 0, 1))
{
context->RootConvertRotation = Quaternion::Euler(90, -90, 0);
}
/*Vector3 engineUp(0, 1, 0);
Vector3 engineFront(0, 0, 1);
Vector3 engineRight(-1, 0, 0);*/
/*Vector3 engineUp(1, 0, 0);
Vector3 engineFront(0, 0, 1);
Vector3 engineRight(0, 1, 0);
/*Float3 engineUp(0, 1, 0);
Float3 engineFront(0, 0, 1);
Float3 engineRight(-1, 0, 0);*/
/*Float3 engineUp(1, 0, 0);
Float3 engineFront(0, 0, 1);
Float3 engineRight(0, 1, 0);
if (context->Up != engineUp || context->Front != engineFront || context->Right != engineRight)
{
LOG(Info, "Converting imported scene nodes to match engine coordinates system");
@@ -1152,10 +1152,10 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
//context->RootConvertRotation *= Quaternion::GetRotationFromTo(rotation * context->Right, engineRight, engineRight);
//context->RootConvertRotation *= Quaternion::GetRotationFromTo(rotation * context->Front, engineFront, engineFront);
}*/
/*Vector3 hackUp = FbxVectorFromAxisAndSign(globalSettings.UpAxis, globalSettings.UpAxisSign);
if (hackUp == Vector3::UnitX)
/*Float3 hackUp = FbxVectorFromAxisAndSign(globalSettings.UpAxis, globalSettings.UpAxisSign);
if (hackUp == Float3::UnitX)
context->RootConvertRotation = Quaternion::Euler(-90, 0, 0);
else if (hackUp == Vector3::UnitZ)
else if (hackUp == Float3::UnitZ)
context->RootConvertRotation = Quaternion::Euler(90, 0, 0);*/
if (!context->RootConvertRotation.IsIdentity())
{

View File

@@ -6,7 +6,7 @@
#include "MeshAccelerationStructure.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/RandomStream.h"
#include "Engine/Core/Math/Int3.h"
#include "Engine/Core/Math/Vector3.h"
#include "Engine/Core/Math/Ray.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Threading/JobSystem.h"
@@ -79,13 +79,13 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
bounds = modelData->LODs[lodIndex].GetBox();
else
return true;
Vector3 size = bounds.GetSize();
Float3 size = bounds.GetSize();
ModelBase::SDFData sdf;
sdf.WorldUnitsPerVoxel = 10 / Math::Max(resolutionScale, 0.0001f);
Int3 resolution(Vector3::Ceil(Vector3::Clamp(size / sdf.WorldUnitsPerVoxel, 4, 256)));
Vector3 uvwToLocalMul = size;
Vector3 uvwToLocalAdd = bounds.Minimum;
sdf.LocalToUVWMul = Vector3::One / uvwToLocalMul;
Int3 resolution(Float3::Ceil(Float3::Clamp(size / sdf.WorldUnitsPerVoxel, 4, 256)));
Float3 uvwToLocalMul = size;
Float3 uvwToLocalAdd = bounds.Minimum;
sdf.LocalToUVWMul = Float3::One / uvwToLocalMul;
sdf.LocalToUVWAdd = -uvwToLocalAdd / uvwToLocalMul;
sdf.MaxDistance = size.MaxValue();
sdf.LocalBoundsMin = bounds.Minimum;
@@ -149,10 +149,10 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
// Allocate memory for the distant field
const int32 voxelsSize = resolution.X * resolution.Y * resolution.Z * formatStride;
void* voxels = Allocator::Allocate(voxelsSize);
Vector3 xyzToLocalMul = uvwToLocalMul / Vector3(resolution);
Vector3 xyzToLocalAdd = uvwToLocalAdd;
const Vector2 encodeMAD(0.5f / sdf.MaxDistance * formatMaxValue, 0.5f * formatMaxValue);
const Vector2 decodeMAD(2.0f * sdf.MaxDistance / formatMaxValue, -sdf.MaxDistance);
Float3 xyzToLocalMul = uvwToLocalMul / Float3(resolution);
Float3 xyzToLocalAdd = uvwToLocalAdd;
const Float2 encodeMAD(0.5f / sdf.MaxDistance * formatMaxValue, 0.5f * formatMaxValue);
const Float2 decodeMAD(2.0f * sdf.MaxDistance / formatMaxValue, -sdf.MaxDistance);
int32 voxelSizeSum = voxelsSize;
// TODO: use optimized sparse storage for SDF data as hierarchical bricks as in papers below:
@@ -163,23 +163,23 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
// Brute-force for each voxel to calculate distance to the closest triangle with point query and distance sign by raycasting around the voxel
const int32 sampleCount = 12;
Array<Vector3> sampleDirections;
Array<Float3> sampleDirections;
sampleDirections.Resize(sampleCount);
{
RandomStream rand;
sampleDirections.Get()[0] = Vector3::Up;
sampleDirections.Get()[1] = Vector3::Down;
sampleDirections.Get()[2] = Vector3::Left;
sampleDirections.Get()[3] = Vector3::Right;
sampleDirections.Get()[4] = Vector3::Forward;
sampleDirections.Get()[5] = Vector3::Backward;
sampleDirections.Get()[0] = Float3::Up;
sampleDirections.Get()[1] = Float3::Down;
sampleDirections.Get()[2] = Float3::Left;
sampleDirections.Get()[3] = Float3::Right;
sampleDirections.Get()[4] = Float3::Forward;
sampleDirections.Get()[5] = Float3::Backward;
for (int32 i = 6; i < sampleCount; i++)
sampleDirections.Get()[i] = rand.GetUnitVector();
}
Function<void(int32)> sdfJob = [&sdf, &resolution, &backfacesThreshold, &sampleDirections, &scene, &voxels, &xyzToLocalMul, &xyzToLocalAdd, &encodeMAD, &formatStride, &formatWrite](int32 z)
{
PROFILE_CPU_NAMED("Model SDF Job");
float hitDistance;
Real hitDistance;
Vector3 hitNormal, hitPoint;
Triangle hitTriangle;
const int32 zAddress = resolution.Y * resolution.X * z;
@@ -188,8 +188,8 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
const int32 yAddress = resolution.X * y + zAddress;
for (int32 x = 0; x < resolution.X; x++)
{
float minDistance = sdf.MaxDistance;
Vector3 voxelPos = Vector3((float)x, (float)y, (float)z) * xyzToLocalMul + xyzToLocalAdd;
Real minDistance = sdf.MaxDistance;
Vector3 voxelPos = Float3((float)x, (float)y, (float)z) * xyzToLocalMul + xyzToLocalAdd;
// Point query to find the distance to the closest surface
scene.PointQuery(voxelPos, minDistance, hitPoint, hitTriangle);
@@ -202,13 +202,13 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
if (scene.RayCast(sampleRay, hitDistance, hitNormal, hitTriangle))
{
hitCount++;
const bool backHit = Vector3::Dot(sampleRay.Direction, hitTriangle.GetNormal()) > 0;
const bool backHit = Float3::Dot(sampleRay.Direction, hitTriangle.GetNormal()) > 0;
if (backHit)
hitBackCount++;
}
}
float distance = minDistance;
float distance = (float)minDistance;
// TODO: surface thickness threshold? shift reduce distance for all voxels by something like 0.01 to enlarge thin geometry
// if ((float)hitBackCount > (float)hitCount * 0.3f && hitCount != 0)
if ((float)hitBackCount > (float)sampleDirections.Count() * backfacesThreshold && hitCount != 0)
@@ -724,7 +724,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
LOG(Warning, "Imported mesh \'{0}\' has missing skinning data. It may result in invalid rendering.", mesh->Name);
auto indices = Int4::Zero;
auto weights = Vector4::UnitX;
auto weights = Float4::UnitX;
// Check if use a single bone for skinning
auto nodeIndex = data.Skeleton.FindNode(mesh->Name);
@@ -876,7 +876,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
}
// Prepare import transformation
Transform importTransform(options.Translation, options.Rotation, Vector3(options.Scale));
Transform importTransform(options.Translation, options.Rotation, Float3(options.Scale));
if (options.CenterGeometry && data.LODs.HasItems() && data.LODs[0].Meshes.HasItems())
{
// Calculate the bounding box (use LOD0 as a reference)
@@ -1031,8 +1031,8 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
const float atlasSizeInv = 1.0f / atlasSize;
for (const auto& entry : entries)
{
Vector2 uvOffset(entry.Slot->X * atlasSizeInv, entry.Slot->Y * atlasSizeInv);
Vector2 uvScale((entry.Slot->Width - chartsPadding) * atlasSizeInv, (entry.Slot->Height - chartsPadding) * atlasSizeInv);
Float2 uvOffset(entry.Slot->X * atlasSizeInv, entry.Slot->Y * atlasSizeInv);
Float2 uvScale((entry.Slot->Width - chartsPadding) * atlasSizeInv, (entry.Slot->Height - chartsPadding) * atlasSizeInv);
// TODO: SIMD
for (auto& uv : entry.Mesh->LightmapUVs)
{
@@ -1407,7 +1407,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
int32 dstMeshIndexCountTarget = int32(srcMeshIndexCount * triangleReduction) / 3 * 3;
Array<unsigned int> indices;
indices.Resize(dstMeshIndexCountTarget);
int32 dstMeshIndexCount = (int32)meshopt_simplifySloppy(indices.Get(), srcMesh->Indices.Get(), srcMeshIndexCount, (const float*)srcMesh->Positions.Get(), srcMeshVertexCount, sizeof(Vector3), dstMeshIndexCountTarget);
int32 dstMeshIndexCount = (int32)meshopt_simplifySloppy(indices.Get(), srcMesh->Indices.Get(), srcMeshIndexCount, (const float*)srcMesh->Positions.Get(), srcMeshVertexCount, sizeof(Float3), dstMeshIndexCountTarget);
indices.Resize(dstMeshIndexCount);
if (dstMeshIndexCount == 0)
continue;
@@ -1429,15 +1429,15 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
dstMesh->name.Resize(dstMeshVertexCount); \
meshopt_remapVertexBuffer(dstMesh->name.Get(), srcMesh->name.Get(), srcMeshVertexCount, sizeof(type), remap.Get()); \
}
REMAP_VERTEX_BUFFER(Positions, Vector3);
REMAP_VERTEX_BUFFER(UVs, Vector2);
REMAP_VERTEX_BUFFER(Normals, Vector3);
REMAP_VERTEX_BUFFER(Tangents, Vector3);
REMAP_VERTEX_BUFFER(Tangents, Vector3);
REMAP_VERTEX_BUFFER(LightmapUVs, Vector2);
REMAP_VERTEX_BUFFER(Positions, Float3);
REMAP_VERTEX_BUFFER(UVs, Float2);
REMAP_VERTEX_BUFFER(Normals, Float3);
REMAP_VERTEX_BUFFER(Tangents, Float3);
REMAP_VERTEX_BUFFER(Tangents, Float3);
REMAP_VERTEX_BUFFER(LightmapUVs, Float2);
REMAP_VERTEX_BUFFER(Colors, Color);
REMAP_VERTEX_BUFFER(BlendIndices, Int4);
REMAP_VERTEX_BUFFER(BlendWeights, Vector4);
REMAP_VERTEX_BUFFER(BlendWeights, Float4);
#undef REMAP_VERTEX_BUFFER
// Remap blend shapes
@@ -1470,7 +1470,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
// Optimize generated LOD
meshopt_optimizeVertexCache(dstMesh->Indices.Get(), dstMesh->Indices.Get(), dstMeshIndexCount, dstMeshVertexCount);
meshopt_optimizeOverdraw(dstMesh->Indices.Get(), dstMesh->Indices.Get(), dstMeshIndexCount, (const float*)dstMesh->Positions.Get(), dstMeshVertexCount, sizeof(Vector3), 1.05f);
meshopt_optimizeOverdraw(dstMesh->Indices.Get(), dstMesh->Indices.Get(), dstMeshIndexCount, (const float*)dstMesh->Positions.Get(), dstMeshVertexCount, sizeof(Float3), 1.05f);
lodTriangleCount += dstMeshIndexCount / 3;
lodVertexCount += dstMeshVertexCount;

View File

@@ -147,13 +147,13 @@ public:
struct ModelSDFHeader
{
Vector3 LocalToUVWMul;
Float3 LocalToUVWMul;
float WorldUnitsPerVoxel;
Vector3 LocalToUVWAdd;
Float3 LocalToUVWAdd;
float MaxDistance;
Vector3 LocalBoundsMin;
Float3 LocalBoundsMin;
int32 MipLevels;
Vector3 LocalBoundsMax;
Float3 LocalBoundsMax;
int32 Width;
int32 Height;
int32 Depth;
@@ -228,7 +228,7 @@ public:
// Animation
AnimationDuration Duration = AnimationDuration::Imported;
Vector2 FramesRange = Vector2::Zero;
Float2 FramesRange = Float2::Zero;
float DefaultFrameRate = 0.0f;
float SamplingRate = 0.0f;
bool SkipEmptyCurves = true;