Merge remote-tracking branch 'origin/master' into 1.1
# Conflicts: # Source/Editor/Surface/SurfaceNode.cs
This commit is contained in:
@@ -15,7 +15,7 @@ void CollisionsHelper::ClosestPointPointLine(const Vector2& point, const Vector2
|
||||
Vector2 n = p1 - p0;
|
||||
|
||||
const float length = n.Length();
|
||||
if (length < 1e-10)
|
||||
if (length < 1e-10f)
|
||||
{
|
||||
// Both points are the same, just give any
|
||||
result = p0;
|
||||
@@ -24,7 +24,7 @@ void CollisionsHelper::ClosestPointPointLine(const Vector2& point, const Vector2
|
||||
n /= length;
|
||||
|
||||
const float dot = Vector2::Dot(n, p);
|
||||
if (dot <= 0.0)
|
||||
if (dot <= 0.0f)
|
||||
{
|
||||
// Before first point
|
||||
result = p0;
|
||||
@@ -41,6 +41,45 @@ void CollisionsHelper::ClosestPointPointLine(const Vector2& point, const Vector2
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 CollisionsHelper::ClosestPointPointLine(const Vector2& point, const Vector2& p0, const Vector2& p1)
|
||||
{
|
||||
Vector2 result;
|
||||
ClosestPointPointLine(point, p0, p1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollisionsHelper::ClosestPointPointLine(const Vector3& point, const Vector3& p0, const Vector3& p1, Vector3& result)
|
||||
{
|
||||
const Vector3 p = point - p0;
|
||||
Vector3 n = p1 - p0;
|
||||
const float length = n.Length();
|
||||
if (length < 1e-10f)
|
||||
{
|
||||
result = p0;
|
||||
return;
|
||||
}
|
||||
n /= length;
|
||||
const float dot = Vector3::Dot(n, p);
|
||||
if (dot <= 0.0f)
|
||||
{
|
||||
result = p0;
|
||||
return;
|
||||
}
|
||||
if (dot >= length)
|
||||
{
|
||||
result = p1;
|
||||
return;
|
||||
}
|
||||
result = p0 + n * dot;
|
||||
}
|
||||
|
||||
Vector3 CollisionsHelper::ClosestPointPointLine(const Vector3& point, const Vector3& p0, const Vector3& p1)
|
||||
{
|
||||
Vector3 result;
|
||||
ClosestPointPointLine(point, p0, p1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollisionsHelper::ClosestPointPointTriangle(const Vector3& point, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Vector3& result)
|
||||
{
|
||||
// Source: Real-Time Collision Detection by Christer Ericson
|
||||
@@ -101,6 +140,13 @@ void CollisionsHelper::ClosestPointPointTriangle(const Vector3& point, const Vec
|
||||
result = vertex1 + ab * v2 + ac * w2; //= u*vertex1 + v*vertex2 + w*vertex3, u = va * denom = 1.0f - v - w
|
||||
}
|
||||
|
||||
Vector3 CollisionsHelper::ClosestPointPointTriangle(const Vector3& point, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3)
|
||||
{
|
||||
Vector3 result;
|
||||
ClosestPointPointTriangle(point, vertex1, vertex2, vertex3, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollisionsHelper::ClosestPointPlanePoint(const Plane& plane, const Vector3& point, Vector3& result)
|
||||
{
|
||||
// Source: Real-Time Collision Detection by Christer Ericson
|
||||
@@ -112,6 +158,13 @@ void CollisionsHelper::ClosestPointPlanePoint(const Plane& plane, const Vector3&
|
||||
result = point - t * plane.Normal;
|
||||
}
|
||||
|
||||
Vector3 CollisionsHelper::ClosestPointPlanePoint(const Plane& plane, const Vector3& point)
|
||||
{
|
||||
Vector3 result;
|
||||
ClosestPointPlanePoint(plane, point, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollisionsHelper::ClosestPointBoxPoint(const BoundingBox& box, const Vector3& point, Vector3& result)
|
||||
{
|
||||
// Source: Real-Time Collision Detection by Christer Ericson
|
||||
@@ -122,6 +175,13 @@ void CollisionsHelper::ClosestPointBoxPoint(const BoundingBox& box, const Vector
|
||||
Vector3::Min(temp, box.Maximum, result);
|
||||
}
|
||||
|
||||
Vector3 CollisionsHelper::ClosestPointBoxPoint(const BoundingBox& box, const Vector3& point)
|
||||
{
|
||||
Vector3 result;
|
||||
ClosestPointBoxPoint(box, point, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollisionsHelper::ClosestPointRectanglePoint(const Rectangle& rect, const Vector2& point, Vector2& result)
|
||||
{
|
||||
Vector2 temp, end;
|
||||
@@ -130,6 +190,13 @@ void CollisionsHelper::ClosestPointRectanglePoint(const Rectangle& rect, const V
|
||||
Vector2::Min(temp, end, result);
|
||||
}
|
||||
|
||||
Vector2 CollisionsHelper::ClosestPointRectanglePoint(const Rectangle& rect, const Vector2& point)
|
||||
{
|
||||
Vector2 result;
|
||||
ClosestPointRectanglePoint(rect, point, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollisionsHelper::ClosestPointSpherePoint(const BoundingSphere& sphere, const Vector3& point, Vector3& result)
|
||||
{
|
||||
// Source: Jorgy343
|
||||
@@ -147,6 +214,13 @@ void CollisionsHelper::ClosestPointSpherePoint(const BoundingSphere& sphere, con
|
||||
result += sphere.Center;
|
||||
}
|
||||
|
||||
Vector3 CollisionsHelper::ClosestPointSpherePoint(const BoundingSphere& sphere, const Vector3& point)
|
||||
{
|
||||
Vector3 result;
|
||||
ClosestPointSpherePoint(sphere, point, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CollisionsHelper::ClosestPointSphereSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2, Vector3& result)
|
||||
{
|
||||
// Source: Jorgy343
|
||||
@@ -164,6 +238,13 @@ void CollisionsHelper::ClosestPointSphereSphere(const BoundingSphere& sphere1, c
|
||||
result += sphere1.Center;
|
||||
}
|
||||
|
||||
Vector3 CollisionsHelper::ClosestPointSphereSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2)
|
||||
{
|
||||
Vector3 result;
|
||||
ClosestPointSphereSphere(sphere1, sphere2, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
float CollisionsHelper::DistancePlanePoint(const Plane& plane, const Vector3& point)
|
||||
{
|
||||
// Source: Real-Time Collision Detection by Christer Ericson
|
||||
@@ -821,7 +902,6 @@ bool CollisionsHelper::RayIntersectsBox(const Ray& ray, const BoundingBox& box,
|
||||
d = Math::Abs(size.Z - Math::Abs(localPoint.Z));
|
||||
if (d < dMin)
|
||||
{
|
||||
dMin = d;
|
||||
normal = Vector3(0, 0, Math::Sign(localPoint.Z));
|
||||
}
|
||||
|
||||
@@ -990,15 +1070,11 @@ PlaneIntersectionType CollisionsHelper::PlaneIntersectsBox(const Plane& plane, c
|
||||
min.Z = plane.Normal.Z >= 0.0f ? box.Maximum.Z : box.Minimum.Z;
|
||||
|
||||
float distance = Vector3::Dot(plane.Normal, max);
|
||||
|
||||
if (distance + plane.D > Plane::DistanceEpsilon)
|
||||
return PlaneIntersectionType::Front;
|
||||
|
||||
distance = Vector3::Dot(plane.Normal, min);
|
||||
|
||||
if (distance + plane.D < Plane::DistanceEpsilon)
|
||||
return PlaneIntersectionType::Back;
|
||||
|
||||
return PlaneIntersectionType::Intersecting;
|
||||
}
|
||||
|
||||
@@ -1012,10 +1088,8 @@ PlaneIntersectionType CollisionsHelper::PlaneIntersectsSphere(const Plane& plane
|
||||
|
||||
if (distance > sphere.Radius)
|
||||
return PlaneIntersectionType::Front;
|
||||
|
||||
if (distance < -sphere.Radius)
|
||||
return PlaneIntersectionType::Back;
|
||||
|
||||
return PlaneIntersectionType::Intersecting;
|
||||
}
|
||||
|
||||
@@ -1023,13 +1097,10 @@ bool CollisionsHelper::BoxIntersectsBox(const BoundingBox& box1, const BoundingB
|
||||
{
|
||||
if (box1.Minimum.X > box2.Maximum.X || box2.Minimum.X > box1.Maximum.X)
|
||||
return false;
|
||||
|
||||
if (box1.Minimum.Y > box2.Maximum.Y || box2.Minimum.Y > box1.Maximum.Y)
|
||||
return false;
|
||||
|
||||
if (box1.Minimum.Z > box2.Maximum.Z || box2.Minimum.Z > box1.Maximum.Z)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,33 @@ public:
|
||||
/// <param name="result">When the method completes, contains the closest point between the two objects.</param>
|
||||
static void ClosestPointPointLine(const Vector2& point, const Vector2& p0, const Vector2& p1, Vector2& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a point and a line.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <param name="p0">The line first point.</param>
|
||||
/// <param name="p1">The line second point.</param>
|
||||
/// <returns>The closest point between the two objects.</result>
|
||||
static Vector2 ClosestPointPointLine(const Vector2& point, const Vector2& p0, const Vector2& p1);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a point and a line.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <param name="p0">The line first point.</param>
|
||||
/// <param name="p1">The line second point.</param>
|
||||
/// <param name="result">When the method completes, contains the closest point between the two objects.</param>
|
||||
static void ClosestPointPointLine(const Vector3& point, const Vector3& p0, const Vector3& p1, Vector3& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a point and a line.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <param name="p0">The line first point.</param>
|
||||
/// <param name="p1">The line second point.</param>
|
||||
/// <returns>The closest point between the two objects.</result>
|
||||
static Vector3 ClosestPointPointLine(const Vector3& point, const Vector3& p0, const Vector3& p1);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a point and a triangle.
|
||||
/// </summary>
|
||||
@@ -82,6 +109,16 @@ public:
|
||||
/// <param name="result">When the method completes, contains the closest point between the two objects.</param>
|
||||
static void ClosestPointPointTriangle(const Vector3& point, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Vector3& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a point and a triangle.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <param name="vertex1">The first vertex to test.</param>
|
||||
/// <param name="vertex2">The second vertex to test.</param>
|
||||
/// <param name="vertex3">The third vertex to test.</param>
|
||||
/// <returns>The closest point between the two objects.</returns>
|
||||
static Vector3 ClosestPointPointTriangle(const Vector3& point, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="Plane" /> and a point.
|
||||
/// </summary>
|
||||
@@ -90,6 +127,14 @@ public:
|
||||
/// <param name="result">When the method completes, contains the closest point between the two objects.</param>
|
||||
static void ClosestPointPlanePoint(const Plane& plane, const Vector3& point, Vector3& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="Plane" /> and a point.
|
||||
/// </summary>
|
||||
/// <param name="plane">The plane to test.</param>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <returns>The closest point between the two objects.</returns>
|
||||
static Vector3 ClosestPointPlanePoint(const Plane& plane, const Vector3& point);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="BoundingBox" /> and a point.
|
||||
/// </summary>
|
||||
@@ -98,6 +143,14 @@ public:
|
||||
/// <param name="result">When the method completes, contains the closest point between the two objects.</param>
|
||||
static void ClosestPointBoxPoint(const BoundingBox& box, const Vector3& point, Vector3& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="BoundingBox" /> and a point.
|
||||
/// </summary>
|
||||
/// <param name="box">The box to test.</param>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <returns>The closest point between the two objects.</returns>
|
||||
static Vector3 ClosestPointBoxPoint(const BoundingBox& box, const Vector3& point);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="Rectangle" /> and a point.
|
||||
/// </summary>
|
||||
@@ -106,6 +159,14 @@ public:
|
||||
/// <param name="result">When the method completes, contains the closest point between the two objects.</param>
|
||||
static void ClosestPointRectanglePoint(const Rectangle& rect, const Vector2& point, Vector2& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="Rectangle" /> and a point.
|
||||
/// </summary>
|
||||
/// <param name="rect">The rectangle to test.</param>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <returns>The closest point between the two objects.</returns>
|
||||
static Vector2 ClosestPointRectanglePoint(const Rectangle& rect, const Vector2& point);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="BoundingSphere" /> and a point.
|
||||
/// </summary>
|
||||
@@ -114,6 +175,14 @@ public:
|
||||
/// <param name="result">When the method completes, contains the closest point between the two objects; or, if the point is directly in the center of the sphere, contains <see cref="Vector3.Zero" />.</param>
|
||||
static void ClosestPointSpherePoint(const BoundingSphere& sphere, const Vector3& point, Vector3& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="BoundingSphere" /> and a point.
|
||||
/// </summary>
|
||||
/// <param name="sphere">The sphere to test.</param>
|
||||
/// <param name="point">The point to test.</param>
|
||||
/// <returns>The closest point between the two objects; or, if the point is directly in the center of the sphere, contains <see cref="Vector3.Zero" />.</return>
|
||||
static Vector3 ClosestPointSpherePoint(const BoundingSphere& sphere, const Vector3& point);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="BoundingSphere" /> and a <see cref="BoundingSphere" />.
|
||||
/// </summary>
|
||||
@@ -127,6 +196,19 @@ public:
|
||||
/// </remarks>
|
||||
static void ClosestPointSphereSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2, Vector3& result);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the closest point between a <see cref="BoundingSphere" /> and a <see cref="BoundingSphere" />.
|
||||
/// </summary>
|
||||
/// <param name="sphere1">The first sphere to test.</param>
|
||||
/// <param name="sphere2">The second sphere to test.</param>
|
||||
/// <returns>The closest point between the two objects; or, if the point is directly in the center of the sphere, contains <see cref="Vector3.Zero" />.</returns>
|
||||
/// <remarks>
|
||||
/// If the two spheres are overlapping, but not directly on top of each other, the closest point
|
||||
/// is the 'closest' point of intersection. This can also be considered is the deepest point of
|
||||
/// intersection.
|
||||
/// </remarks>
|
||||
static Vector3 ClosestPointSphereSphere(const BoundingSphere& sphere1, const BoundingSphere& sphere2);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the distance between a <see cref="Plane" /> and a point.
|
||||
/// </summary>
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace FlaxEngine
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
@@ -163,7 +163,7 @@ namespace FlaxEngine
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
@@ -210,7 +210,7 @@ namespace FlaxEngine
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
@@ -257,7 +257,7 @@ namespace FlaxEngine
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
|
||||
@@ -10,6 +10,127 @@
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include <ThirdParty/mono-2.0/mono/metadata/appdomain.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename IndexType>
|
||||
bool UpdateMesh(Mesh* mesh, uint32 vertexCount, uint32 triangleCount, Vector3* vertices, IndexType* triangles, Vector3* normals, Vector3* tangents, Vector2* uvs, Color32* colors)
|
||||
{
|
||||
auto model = mesh->GetModel();
|
||||
CHECK_RETURN(model && model->IsVirtual(), true);
|
||||
CHECK_RETURN(triangles && vertices, true);
|
||||
|
||||
// Pack mesh data into vertex buffers
|
||||
Array<VB1ElementType> vb1;
|
||||
Array<VB2ElementType> vb2;
|
||||
vb1.Resize(vertexCount);
|
||||
if (normals)
|
||||
{
|
||||
if (tangents)
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
const Vector3 normal = normals[i];
|
||||
const Vector3 tangent = tangents[i];
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
const Vector3 normal = normals[i];
|
||||
|
||||
// Calculate tangent
|
||||
Vector3 c1 = Vector3::Cross(normal, Vector3::UnitZ);
|
||||
Vector3 c2 = Vector3::Cross(normal, Vector3::UnitY);
|
||||
Vector3 tangent;
|
||||
if (c1.LengthSquared() > c2.LengthSquared())
|
||||
tangent = c1;
|
||||
else
|
||||
tangent = c2;
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set default tangent frame
|
||||
const auto n = Float1010102(Vector3::UnitZ);
|
||||
const auto t = Float1010102(Vector3::UnitX);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
vb1[i].Normal = n;
|
||||
vb1[i].Tangent = t;
|
||||
}
|
||||
}
|
||||
if (uvs)
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = Half2(uvs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = v;
|
||||
}
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].LightmapUVs = v;
|
||||
}
|
||||
if (colors)
|
||||
{
|
||||
vb2.Resize(vertexCount);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb2[i].Color = colors[i];
|
||||
}
|
||||
|
||||
return mesh->UpdateMesh(vertexCount, triangleCount, (VB0ElementType*)vertices, vb1.Get(), vb2.HasItems() ? vb2.Get() : nullptr, triangles);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateMesh(Mesh* mesh, uint32 vertexCount, uint32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
{
|
||||
ASSERT((uint32)mono_array_length(verticesObj) >= vertexCount);
|
||||
ASSERT((uint32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto vertices = (Vector3*)(void*)mono_array_addr_with_size(verticesObj, sizeof(Vector3), 0);
|
||||
auto triangles = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
const auto normals = normalsObj ? (Vector3*)(void*)mono_array_addr_with_size(normalsObj, sizeof(Vector3), 0) : nullptr;
|
||||
const auto tangents = tangentsObj ? (Vector3*)(void*)mono_array_addr_with_size(tangentsObj, sizeof(Vector3), 0) : nullptr;
|
||||
const auto uvs = uvObj ? (Vector2*)(void*)mono_array_addr_with_size(uvObj, sizeof(Vector2), 0) : nullptr;
|
||||
const auto colors = colorsObj ? (Color32*)(void*)mono_array_addr_with_size(colorsObj, sizeof(Color32), 0) : nullptr;
|
||||
return UpdateMesh<IndexType>(mesh, vertexCount, triangleCount, vertices, triangles, normals, tangents, uvs, colors);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateTriangles(Mesh* mesh, int32 triangleCount, MonoArray* trianglesObj)
|
||||
{
|
||||
const auto model = mesh->GetModel();
|
||||
ASSERT(model && model->IsVirtual() && trianglesObj);
|
||||
|
||||
// Get buffer data
|
||||
ASSERT((int32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto ib = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
|
||||
return mesh->UpdateTriangles(triangleCount, ib);
|
||||
}
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, void* ib, bool use16BitIndices)
|
||||
{
|
||||
Unload();
|
||||
@@ -31,6 +152,16 @@ bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType*
|
||||
return failed;
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint16* triangles, Vector3* normals, Vector3* tangents, Vector2* uvs, Color32* colors)
|
||||
{
|
||||
return ::UpdateMesh<uint16>(this, vertexCount, triangleCount, vertices, triangles, normals, tangents, uvs, colors);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint32* triangles, Vector3* normals, Vector3* tangents, Vector2* uvs, Color32* colors)
|
||||
{
|
||||
return ::UpdateMesh<uint32>(this, vertexCount, triangleCount, vertices, triangles, normals, tangents, uvs, colors);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateTriangles(uint32 triangleCount, void* ib, bool use16BitIndices)
|
||||
{
|
||||
// Cache data
|
||||
@@ -384,108 +515,9 @@ ScriptingObject* Mesh::GetParentModel()
|
||||
return _model;
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateMesh(Mesh* mesh, uint32 vertexCount, uint32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
{
|
||||
auto model = mesh->GetModel();
|
||||
ASSERT(model && model->IsVirtual() && verticesObj && trianglesObj);
|
||||
|
||||
// Get buffers data
|
||||
ASSERT((uint32)mono_array_length(verticesObj) >= vertexCount);
|
||||
ASSERT((uint32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto vb0 = (Vector3*)(void*)mono_array_addr_with_size(verticesObj, sizeof(Vector3), 0);
|
||||
auto ib = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
Array<VB1ElementType> vb1;
|
||||
Array<VB2ElementType> vb2;
|
||||
vb1.Resize(vertexCount);
|
||||
if (normalsObj)
|
||||
{
|
||||
const auto normals = (Vector3*)(void*)mono_array_addr_with_size(normalsObj, sizeof(Vector3), 0);
|
||||
if (tangentsObj)
|
||||
{
|
||||
const auto tangents = (Vector3*)(void*)mono_array_addr_with_size(tangentsObj, sizeof(Vector3), 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
// Peek normal and tangent
|
||||
const Vector3 normal = normals[i];
|
||||
const Vector3 tangent = tangents[i];
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
// Peek normal
|
||||
const Vector3 normal = normals[i];
|
||||
|
||||
// Calculate tangent
|
||||
Vector3 c1 = Vector3::Cross(normal, Vector3::UnitZ);
|
||||
Vector3 c2 = Vector3::Cross(normal, Vector3::UnitY);
|
||||
Vector3 tangent;
|
||||
if (c1.LengthSquared() > c2.LengthSquared())
|
||||
tangent = c1;
|
||||
else
|
||||
tangent = c2;
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto n = Float1010102(Vector3::UnitZ);
|
||||
const auto t = Float1010102(Vector3::UnitX);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
vb1[i].Normal = n;
|
||||
vb1[i].Tangent = t;
|
||||
}
|
||||
}
|
||||
if (uvObj)
|
||||
{
|
||||
const auto uvs = (Vector2*)(void*)mono_array_addr_with_size(uvObj, sizeof(Vector2), 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = Half2(uvs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = v;
|
||||
}
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].LightmapUVs = v;
|
||||
}
|
||||
if (colorsObj)
|
||||
{
|
||||
vb2.Resize(vertexCount);
|
||||
const auto colors = (Color32*)(void*)mono_array_addr_with_size(colorsObj, sizeof(Color32), 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb2[i].Color = colors[i];
|
||||
}
|
||||
|
||||
return mesh->UpdateMesh(vertexCount, triangleCount, (VB0ElementType*)vb0, vb1.Get(), vb2.HasItems() ? vb2.Get() : nullptr, ib);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMeshInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
{
|
||||
return ::UpdateMesh<int32>(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj);
|
||||
return ::UpdateMesh<uint32>(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMeshUShort(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
@@ -493,22 +525,9 @@ bool Mesh::UpdateMeshUShort(int32 vertexCount, int32 triangleCount, MonoArray* v
|
||||
return ::UpdateMesh<uint16>(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateTriangles(Mesh* mesh, int32 triangleCount, MonoArray* trianglesObj)
|
||||
{
|
||||
auto model = mesh->GetModel();
|
||||
ASSERT(model && model->IsVirtual() && trianglesObj);
|
||||
|
||||
// Get buffer data
|
||||
ASSERT((int32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto ib = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
|
||||
return mesh->UpdateTriangles(triangleCount, ib);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateTrianglesInt(int32 triangleCount, MonoArray* trianglesObj)
|
||||
{
|
||||
return ::UpdateTriangles<int32>(this, triangleCount, trianglesObj);
|
||||
return ::UpdateTriangles<uint32>(this, triangleCount, trianglesObj);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateTrianglesUShort(int32 triangleCount, MonoArray* trianglesObj)
|
||||
|
||||
@@ -216,9 +216,9 @@ public:
|
||||
/// <param name="vb0">The first vertex buffer data.</param>
|
||||
/// <param name="vb1">The second vertex buffer data.</param>
|
||||
/// <param name="vb2">The third vertex buffer data.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <param name="ib">The index buffer in clockwise order.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, int32* ib)
|
||||
FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, uint32* ib)
|
||||
{
|
||||
return UpdateMesh(vertexCount, triangleCount, vb0, vb1, vb2, ib, false);
|
||||
}
|
||||
@@ -231,7 +231,7 @@ public:
|
||||
/// <param name="vb0">The first vertex buffer data.</param>
|
||||
/// <param name="vb1">The second vertex buffer data.</param>
|
||||
/// <param name="vb2">The third vertex buffer data.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <param name="ib">The index buffer in clockwise order.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, uint16* ib)
|
||||
{
|
||||
@@ -240,17 +240,51 @@ public:
|
||||
|
||||
/// <summary>
|
||||
/// Updates the model mesh (used by the virtual models created with Init rather than Load).
|
||||
/// Can be used only for virtual assets (see <see cref="Asset.IsVirtual"/> and <see cref="Content.CreateVirtualAsset{T}"/>).
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vb0">The first vertex buffer data.</param>
|
||||
/// <param name="vb1">The second vertex buffer data.</param>
|
||||
/// <param name="vb2">The third vertex buffer data.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <param name="ib">The index buffer in clockwise order.</param>
|
||||
/// <param name="use16BitIndices">True if index buffer uses 16-bit index buffer, otherwise 32-bit.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, void* ib, bool use16BitIndices);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the model mesh (used by the virtual models created with Init rather than Load).
|
||||
/// Can be used only for virtual assets (see <see cref="Asset.IsVirtual"/> and <see cref="Content.CreateVirtualAsset{T}"/>).
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint16* triangles, Vector3* normals = nullptr, Vector3* tangents = nullptr, Vector2* uvs = nullptr, Color32* colors = nullptr);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the model mesh (used by the virtual models created with Init rather than Load).
|
||||
/// Can be used only for virtual assets (see <see cref="Asset.IsVirtual"/> and <see cref="Content.CreateVirtualAsset{T}"/>).
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint32* triangles, Vector3* normals = nullptr, Vector3* tangents = nullptr, Vector2* uvs = nullptr, Color32* colors = nullptr);
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
@@ -259,7 +293,7 @@ public:
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
FORCE_INLINE bool UpdateTriangles(uint32 triangleCount, int32* ib)
|
||||
FORCE_INLINE bool UpdateTriangles(uint32 triangleCount, uint32* ib)
|
||||
{
|
||||
return UpdateTriangles(triangleCount, ib, false);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vb">The vertex buffer data.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <param name="ib">The index buffer in clockwise order.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0SkinnedElementType* vb, int32* ib)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vb">The vertex buffer data.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <param name="ib">The index buffer, clockwise order.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0SkinnedElementType* vb, uint16* ib)
|
||||
{
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vb">The vertex buffer data.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <param name="ib">The index buffer in clockwise order.</param>
|
||||
/// <param name="use16BitIndices">True if index buffer uses 16-bit index buffer, otherwise 32-bit.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0SkinnedElementType* vb, void* ib, bool use16BitIndices);
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace FlaxEngine
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
@@ -140,7 +140,7 @@ namespace FlaxEngine
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
|
||||
@@ -55,7 +55,7 @@ void CharacterController::SetHeight(const float value)
|
||||
|
||||
void CharacterController::SetSlopeLimit(float value)
|
||||
{
|
||||
value = Math::Clamp(value, 0.0f, 90.0f);
|
||||
value = Math::Clamp(value, 0.0f, 89.0f);
|
||||
if (Math::NearEqual(value, _slopeLimit))
|
||||
return;
|
||||
|
||||
@@ -177,7 +177,7 @@ void CharacterController::CreateActor()
|
||||
const float scaling = _cachedScale.GetAbsolute().MaxValue();
|
||||
const float minSize = 0.001f;
|
||||
desc.height = Math::Max(Math::Abs(_height) * scaling, minSize);
|
||||
desc.radius = Math::Max(Math::Abs(_radius) * scaling, minSize);
|
||||
desc.radius = Math::Max(Math::Abs(_radius) * scaling - desc.contactOffset, minSize);
|
||||
|
||||
// Create controller
|
||||
_controller = (PxCapsuleController*)Physics::GetControllerManager()->createController(desc);
|
||||
@@ -202,7 +202,7 @@ void CharacterController::UpdateSize() const
|
||||
{
|
||||
const float scaling = _cachedScale.GetAbsolute().MaxValue();
|
||||
const float minSize = 0.001f;
|
||||
const float radius = Math::Max(Math::Abs(_radius) * scaling, minSize);
|
||||
const float radius = Math::Max(Math::Abs(_radius) * scaling - Math::Max(_contactOffset, ZeroTolerance), minSize);
|
||||
const float height = Math::Max(Math::Abs(_height) * scaling, minSize);
|
||||
|
||||
_controller->setRadius(radius);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "WindowsFileSystem.h"
|
||||
#include "Engine/Platform/File.h"
|
||||
#include "Engine/Platform/Window.h"
|
||||
#include "Engine/Platform/Windows/ComPtr.h"
|
||||
#include "Engine/Core/Types/StringView.h"
|
||||
#include "../Win32/IncludeWindowsHeaders.h"
|
||||
|
||||
@@ -293,41 +294,39 @@ bool WindowsFileSystem::ShowBrowseFolderDialog(Window* parentWindow, const Strin
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
// Allocate memory for the filenames
|
||||
int32 maxPathSize = 2 * MAX_PATH;
|
||||
Array<Char> pathBuffer;
|
||||
pathBuffer.Resize(maxPathSize);
|
||||
pathBuffer[0] = 0;
|
||||
// Randomly generated GUID used for storing the last location of this dialog
|
||||
const Guid folderGuid(0x53890ed9, 0xa55e47ba, 0xa970bdae, 0x72acedff);
|
||||
|
||||
// Setup description
|
||||
BROWSEINFOW bi;
|
||||
ZeroMemory(&bi, sizeof(bi));
|
||||
if (parentWindow)
|
||||
bi.hwndOwner = static_cast<HWND>(parentWindow->GetNativePtr());
|
||||
bi.lpszTitle = title.HasChars() ? title.Get() : nullptr;
|
||||
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
|
||||
bi.lpfn = BrowseCallbackProc;
|
||||
bi.lParam = (LPARAM)(initialDirectory.HasChars() ? initialDirectory.Get() : nullptr);
|
||||
|
||||
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
||||
|
||||
if (pidl != nullptr)
|
||||
ComPtr<IFileOpenDialog> fd;
|
||||
if (SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&fd))))
|
||||
{
|
||||
// Get the name of the folder and put it in path
|
||||
SHGetPathFromIDList(pidl, pathBuffer.Get());
|
||||
DWORD options;
|
||||
fd->GetOptions(&options);
|
||||
fd->SetOptions(options | FOS_PICKFOLDERS | FOS_NOCHANGEDIR);
|
||||
|
||||
if (pathBuffer[0] != 0)
|
||||
{
|
||||
path = pathBuffer.Get();
|
||||
result = false;
|
||||
}
|
||||
if (title.HasChars())
|
||||
fd->SetTitle(title.Get());
|
||||
|
||||
// Free memory used
|
||||
IMalloc* imalloc = 0;
|
||||
if (SUCCEEDED(SHGetMalloc(&imalloc)))
|
||||
// Associate the last selected folder with this GUID instead of overwriting the global one
|
||||
fd->SetClientGuid(*reinterpret_cast<const GUID*>(&folderGuid));
|
||||
|
||||
ComPtr<IShellItem> defaultFolder;
|
||||
if (SUCCEEDED(SHCreateItemFromParsingName(initialDirectory.Get(), NULL, IID_PPV_ARGS(&defaultFolder))))
|
||||
fd->SetFolder(defaultFolder);
|
||||
|
||||
if (SUCCEEDED(fd->Show(parentWindow->GetHWND())))
|
||||
{
|
||||
imalloc->Free(pidl);
|
||||
imalloc->Release();
|
||||
ComPtr<IShellItem> si;
|
||||
if (SUCCEEDED(fd->GetResult(&si)))
|
||||
{
|
||||
LPWSTR resultPath;
|
||||
if (SUCCEEDED(si->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &resultPath)))
|
||||
{
|
||||
path = resultPath;
|
||||
CoTaskMemFree(resultPath);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -274,8 +274,10 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value)
|
||||
// Compute depth difference
|
||||
auto depthDiff = writeLocal(VariantType::Float, String::Format(TEXT("{0} * ViewFar - {1}"), sceneDepth.Value, posVS.Value), node);
|
||||
|
||||
auto fadeDistance = tryGetValue(node->GetBox(0), node->Values[0]).AsFloat();
|
||||
|
||||
// Apply smoothing factor and clamp the result
|
||||
value = writeLocal(VariantType::Float, String::Format(TEXT("saturate({0} / {1})"), depthDiff.Value, node->Values[0].AsFloat), node);
|
||||
value = writeLocal(VariantType::Float, String::Format(TEXT("saturate({0} / {1})"), depthDiff.Value, fadeDistance.Value), node);
|
||||
break;
|
||||
}
|
||||
// Material Function
|
||||
@@ -337,6 +339,59 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value)
|
||||
case 25:
|
||||
value = Value(VariantType::Vector3, TEXT("GetObjectSize(input)"));
|
||||
break;
|
||||
// Blend Normals
|
||||
case 26:
|
||||
{
|
||||
const auto baseNormal = tryGetValue(node->GetBox(0), Value::Zero).AsVector3();
|
||||
const auto additionalNormal = tryGetValue(node->GetBox(1), Value::Zero).AsVector3();
|
||||
const String text = String::Format(TEXT("float3((float2({0}.xy) + float2({1}.xy) * 2.0), sqrt(saturate(1.0 - dot((float2({0}.xy) + float2({1}.xy) * 2.0).xy, (float2({0}.xy) + float2({1}.xy) * 2.0).xy))))"), baseNormal.Value, additionalNormal.Value);
|
||||
value = writeLocal(ValueType::Vector3, text, node);
|
||||
break;
|
||||
}
|
||||
// Rotator
|
||||
case 27:
|
||||
{
|
||||
auto uv = tryGetValue(node->GetBox(0), getUVs).AsVector2();
|
||||
auto center = tryGetValue(node->GetBox(1), Value::Zero).AsVector2();
|
||||
auto rotationAngle = tryGetValue(node->GetBox(2), Value::Zero).AsFloat();
|
||||
|
||||
const auto x1 = writeLocal(ValueType::Vector2, String::Format(TEXT("({0} * -1) + {1}"), center.Value, uv.Value), node);
|
||||
const auto raCosSin = writeLocal(ValueType::Vector2, String::Format(TEXT("float2(cos({0}), sin({0}))"), rotationAngle.Value), node);
|
||||
|
||||
const auto dotB1 = writeLocal(ValueType::Vector2, String::Format(TEXT("float2({0}.x, {0}.y * -1)"), raCosSin.Value), node);
|
||||
const auto dotB2 = writeLocal(ValueType::Vector2, String::Format(TEXT("float2({0}.y, {0}.x)"), raCosSin.Value), node);
|
||||
|
||||
value = writeLocal(ValueType::Vector2, String::Format(TEXT("{3} + float2(dot({0},{1}), dot({0},{2}))"), x1.Value, dotB1.Value, dotB2.Value, center.Value), node);
|
||||
break;
|
||||
}
|
||||
// Sphere Mask
|
||||
case 28:
|
||||
{
|
||||
Value a = tryGetValue(node->GetBox(0), 0, Value::Zero);
|
||||
Value b = tryGetValue(node->GetBox(1), 1, Value::Zero).Cast(a.Type);
|
||||
Value radius = tryGetValue(node->GetBox(2), node->Values[0]).AsFloat();
|
||||
Value hardness = tryGetValue(node->GetBox(3), node->Values[1]).AsFloat();
|
||||
Value invert = tryGetValue(node->GetBox(4), node->Values[2]).AsBool();
|
||||
|
||||
// Get distance and apply radius
|
||||
auto x1 = writeLocal(ValueType::Float, String::Format(TEXT("distance({0},{1}) * (1 / {2})"), a.Value, b.Value, radius.Value), node);
|
||||
|
||||
// Apply hardness, use 0.991 as max since any value above will result in harsh aliasing
|
||||
auto x2 = writeLocal(ValueType::Float, String::Format(TEXT("saturate((1 - {0}) * (1 / (1 - clamp({1}, 0, 0.991f))))"), x1.Value, hardness.Value), node);
|
||||
|
||||
value = writeLocal(ValueType::Float, String::Format(TEXT("{0} ? (1 - {1}) : {1}"), invert.Value, x2.Value), node);
|
||||
break;
|
||||
}
|
||||
// Tiling & Offset
|
||||
case 29:
|
||||
{
|
||||
auto uv = tryGetValue(node->GetBox(0), getUVs).AsVector2();
|
||||
auto tiling = tryGetValue(node->GetBox(1), node->Values[0]).AsVector2();
|
||||
auto offset = tryGetValue(node->GetBox(2), node->Values[1]).AsVector2();
|
||||
|
||||
value = writeLocal(ValueType::Vector2, String::Format(TEXT("{0} * {1} + {2}"), uv.Value, tiling.Value, offset.Value), node);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -190,6 +190,16 @@ bool TextureTool::ExportTextureDirectXTex(ImageType type, const StringView& path
|
||||
}
|
||||
img = tmp.GetImage(0, 0, 0);
|
||||
}
|
||||
else if (image.format == DXGI_FORMAT_R10G10B10A2_UNORM || image.format == DXGI_FORMAT_R11G11B10_FLOAT)
|
||||
{
|
||||
result = DirectX::Convert(image, DXGI_FORMAT_R8G8B8A8_UNORM, DirectX::TEX_FILTER_DEFAULT, DirectX::TEX_THRESHOLD_DEFAULT, tmp);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG(Error, "Cannot convert texture, error: {0:x}", static_cast<uint32>(result));
|
||||
return true;
|
||||
}
|
||||
img = tmp.GetImage(0, 0, 0);
|
||||
}
|
||||
|
||||
DirectX::WICCodecs codec;
|
||||
switch (type)
|
||||
|
||||
@@ -401,6 +401,18 @@ void ShaderGenerator::ProcessGroupMath(Box* box, Node* node, Value& value)
|
||||
{
|
||||
value = writeFunction1(node, tryGetValue(node->GetBox(0), Value::Zero), TEXT("radians"));
|
||||
break;
|
||||
}
|
||||
// Remap
|
||||
case 48:
|
||||
{
|
||||
const auto inVal = tryGetValue(node->GetBox(0), node->Values[0].AsFloat);
|
||||
const auto rangeA = tryGetValue(node->GetBox(1), node->Values[1].AsVector2());
|
||||
const auto rangeB = tryGetValue(node->GetBox(2), node->Values[2].AsVector2());
|
||||
const auto clamp = tryGetValue(node->GetBox(3), node->Values[3]).AsBool();
|
||||
|
||||
const auto mapFunc = String::Format(TEXT("{2}.x + ({0} - {1}.x) * ({2}.y - {2}.x) / ({1}.y - {1}.x)"), inVal.Value, rangeA.Value, rangeB.Value);
|
||||
value = writeLocal(ValueType::Float, String::Format(TEXT("{2} ? clamp({0}, {1}.x, {1}.y) : {0}"), mapFunc, rangeB.Value, clamp.Value), node);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -371,6 +371,20 @@ void VisjectExecutor::ProcessGroupMath(Box* box, Node* node, Value& value)
|
||||
if (value.Type.Type == VariantType::Enum)
|
||||
value.AsUint64 = value.AsUint64 | (uint64)tryGetValue(node->GetBox(1), Value::Zero);
|
||||
break;
|
||||
// Remap
|
||||
case 48:
|
||||
{
|
||||
const float inVal = tryGetValue(node->GetBox(0), node->Values[0]).AsFloat;
|
||||
const Vector2 rangeA = tryGetValue(node->GetBox(1), node->Values[1]).AsVector2();
|
||||
const Vector2 rangeB = tryGetValue(node->GetBox(2), node->Values[2]).AsVector2();
|
||||
const bool clamp = tryGetValue(node->GetBox(3), node->Values[3]).AsBool;
|
||||
|
||||
auto mapFunc = rangeB.X + (inVal - rangeA.X) * (rangeB.Y - rangeB.X) / (rangeA.Y - rangeA.X);
|
||||
|
||||
// Clamp value?
|
||||
value = clamp ? Math::Clamp(mapFunc, rangeB.X, rangeB.Y) : mapFunc;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user