Fix foliage instance bounds calculations regression from 486781661e

Using matrix transformation doesn't work properly on some foliage.
Add `BoundingSphere.Transform` with `Transform` instead of `Matrix`
This commit is contained in:
2026-08-03 13:48:22 +02:00
parent 8632890068
commit c3cea5e788
4 changed files with 48 additions and 16 deletions
@@ -4,6 +4,7 @@
#include "BoundingBox.h"
#include "Matrix.h"
#include "Ray.h"
#include "Transform.h"
#include "../Types/String.h"
const BoundingSphere BoundingSphere::Empty(Vector3(0, 0, 0), 0);
@@ -220,3 +221,9 @@ void BoundingSphere::Transform(const BoundingSphere& sphere, const Matrix& matri
Vector3::Transform(sphere.Center, matrix, result.Center);
result.Radius = sphere.Radius * matrix.GetScaleVector().GetAbsolute().MaxValue();
}
void BoundingSphere::Transform(const BoundingSphere& sphere, const ::Transform& transform, BoundingSphere& result)
{
Vector3::Transform(sphere.Center, transform, result.Center);
result.Radius = sphere.Radius * transform.Scale.GetAbsolute().MaxValue();
}
+24
View File
@@ -393,6 +393,30 @@ namespace FlaxEngine
result.Radius = sphere.Radius * matrix.ScaleVector.Absolute.MaxValue;
}
/// <summary>
/// Transforms the bounding sphere using the specified transformation.
/// </summary>
/// <param name="sphere">The sphere.</param>
/// <param name="transform">The transform.</param>
/// <remarks>The result transformed sphere.</remarks>
public static BoundingSphere Transform(BoundingSphere sphere, Transform transform)
{
Transform(ref sphere, ref transform, out var result);
return result;
}
/// <summary>
/// Transforms the bounding sphere using the specified transformation.
/// </summary>
/// <param name="sphere">The sphere.</param>
/// <param name="transform">The transform.</param>
/// <param name="result">The result transformed sphere.</param>
public static void Transform(ref BoundingSphere sphere, ref Transform transform, out BoundingSphere result)
{
Vector3.Transform(ref sphere.Center, ref transform, out result.Center);
result.Radius = sphere.Radius * transform.Scale.Absolute.MaxValue;
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
+8
View File
@@ -224,6 +224,14 @@ public:
/// <param name="matrix">The matrix.</param>
/// <param name="result">The result transformed sphere.</param>
static void Transform(const BoundingSphere& sphere, const Matrix& matrix, BoundingSphere& result);
/// <summary>
/// Transforms the bounding sphere using the specified transformation.
/// </summary>
/// <param name="sphere">The sphere.</param>
/// <param name="transform">The transform.</param>
/// <param name="result">The result transformed sphere.</param>
static void Transform(const BoundingSphere& sphere, const ::Transform& transform, BoundingSphere& result);
};
template<>
+9 -16
View File
@@ -653,7 +653,7 @@ void Foliage::UpdateBounds()
typeBounds.Resize(FoliageTypes.Count());
for (int32 i = 0; i < typeBounds.Count(); i++)
{
auto& type = FoliageTypes[i];
const auto& type = FoliageTypes[i];
bool ready = type.IsReady();
typeReady.Set(i, ready);
if (ready)
@@ -661,16 +661,14 @@ void Foliage::UpdateBounds()
}
// Update bounds for all instances
Matrix foliageWorld, instanceLocal, instanceWorld;
GetLocalToWorldMatrix(foliageWorld);
Transform globalTransform = _transform, transform;
for (auto i = Instances.Begin(); i.IsNotEnd(); ++i)
{
auto& instance = *i;
if (typeReady.Get(instance.Type))
{
instance.Transform.GetWorld(instanceLocal);
Matrix::Multiply(foliageWorld, instanceLocal, instanceWorld);
BoundingSphere::Transform(typeBounds[instance.Type], instanceWorld, instance.Bounds);
globalTransform.LocalToWorld(instance.Transform, transform);
BoundingSphere::Transform(typeBounds[instance.Type], transform, instance.Bounds);
}
else
{
@@ -837,11 +835,8 @@ void Foliage::SetInstanceTransform(int32 index, const Transform& value)
{
BoundingSphere typeBounds;
BoundingSphere::FromBox(type.Model->GetBox(), typeBounds);
Matrix foliageWorld, instanceLocal, instanceWorld;
GetLocalToWorldMatrix(foliageWorld);
instance.Transform.GetWorld(instanceLocal);
Matrix::Multiply(foliageWorld, instanceLocal, instanceWorld);
BoundingSphere::Transform(typeBounds, instanceWorld, instance.Bounds);
const Transform transform = _transform.LocalToWorld(instance.Transform);
BoundingSphere::Transform(typeBounds, transform, instance.Bounds);
}
else
{
@@ -868,8 +863,7 @@ void Foliage::OnFoliageTypeModelLoaded(int32 index)
BoundingSphere typeBounds;
BoundingSphere::FromBox(type.Model->GetBox(), typeBounds);
Matrix foliageWorld, instanceLocal, instanceWorld;
GetLocalToWorldMatrix(foliageWorld);
Transform globalTransform = _transform, transform;
for (auto i = Instances.Begin(); i.IsNotEnd(); ++i)
{
@@ -877,9 +871,8 @@ void Foliage::OnFoliageTypeModelLoaded(int32 index)
if (instance.Type != index)
continue;
instance.Transform.GetWorld(instanceLocal);
Matrix::Multiply(foliageWorld, instanceLocal, instanceWorld);
BoundingSphere::Transform(typeBounds, instanceWorld, instance.Bounds);
globalTransform.LocalToWorld(instance.Transform, transform);
BoundingSphere::Transform(typeBounds, transform, instance.Bounds);
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
BoundingBox::FromSphere(instance.Bounds, box);