Fix transform scaling applying to nested objects when drawing

#1796 #1350
This commit is contained in:
Wojtek Figat
2024-02-20 23:55:06 +01:00
parent e5cfd872b2
commit 9a21cfd092
13 changed files with 51 additions and 30 deletions

View File

@@ -658,7 +658,7 @@ namespace FlaxEditor.SceneGraph.GUI
} }
} }
actor.Name = item.ShortName; actor.Name = item.ShortName;
if (_dragAssets.Objects[i] is not PrefabItem p) if (_dragAssets.Objects[i] is not PrefabItem)
actor.Transform = Transform.Identity; actor.Transform = Transform.Identity;
var previousTrans = actor.Transform; var previousTrans = actor.Transform;
ActorNode.Root.Spawn(actor, spawnParent); ActorNode.Root.Spawn(actor, spawnParent);

View File

@@ -335,4 +335,12 @@ public:
// Calculates the world matrix for the given transformation instance rendering. // Calculates the world matrix for the given transformation instance rendering.
void GetWorldMatrix(const Transform& transform, Matrix& world) const; void GetWorldMatrix(const Transform& transform, Matrix& world) const;
// Applies the render origin to the transformation instance matrix.
FORCE_INLINE void GetWorldMatrix(Matrix& world) const
{
world.M41 -= Origin.X;
world.M42 -= Origin.Y;
world.M43 -= Origin.Z;
}
}; };

View File

@@ -657,7 +657,7 @@ void Actor::SetScale(const Float3& value)
if (!Float3::NearEqual(_transform.Scale, value)) if (!Float3::NearEqual(_transform.Scale, value))
{ {
if (_parent) if (_parent)
Float3::Divide(value, _parent->GetScale(), _localTransform.Scale); Float3::Divide(value, _parent->_transform.Scale, _localTransform.Scale);
else else
_localTransform.Scale = value; _localTransform.Scale = value;
OnTransformChanged(); OnTransformChanged();
@@ -753,10 +753,25 @@ void Actor::AddMovement(const Vector3& translation, const Quaternion& rotation)
void Actor::GetWorldToLocalMatrix(Matrix& worldToLocal) const void Actor::GetWorldToLocalMatrix(Matrix& worldToLocal) const
{ {
_transform.GetWorld(worldToLocal); GetLocalToWorldMatrix(worldToLocal);
worldToLocal.Invert(); worldToLocal.Invert();
} }
void Actor::GetLocalToWorldMatrix(Matrix& localToWorld) const
{
#if 0
_transform.GetWorld(localToWorld);
#else
_localTransform.GetWorld(localToWorld);
if (_parent)
{
Matrix parentToWorld;
_parent->GetLocalToWorldMatrix(parentToWorld);
localToWorld = localToWorld * parentToWorld;
}
#endif
}
void Actor::LinkPrefab(const Guid& prefabId, const Guid& prefabObjectId) void Actor::LinkPrefab(const Guid& prefabId, const Guid& prefabObjectId)
{ {
ASSERT(prefabId.IsValid()); ASSERT(prefabId.IsValid());

View File

@@ -638,10 +638,7 @@ public:
/// Gets the matrix that transforms a point from the local space of the actor to world space. /// Gets the matrix that transforms a point from the local space of the actor to world space.
/// </summary> /// </summary>
/// <param name="localToWorld">The world to local matrix.</param> /// <param name="localToWorld">The world to local matrix.</param>
API_FUNCTION() FORCE_INLINE void GetLocalToWorldMatrix(API_PARAM(Out) Matrix& localToWorld) const API_FUNCTION() void GetLocalToWorldMatrix(API_PARAM(Out) Matrix& localToWorld) const;
{
_transform.GetWorld(localToWorld);
}
public: public:
/// <summary> /// <summary>

View File

@@ -127,7 +127,7 @@ void AnimatedModel::GetCurrentPose(Array<Matrix>& nodesTransformation, bool worl
if (worldSpace) if (worldSpace)
{ {
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
for (auto& m : nodesTransformation) for (auto& m : nodesTransformation)
m = m * world; m = m * world;
} }
@@ -142,7 +142,7 @@ void AnimatedModel::SetCurrentPose(const Array<Matrix>& nodesTransformation, boo
if (worldSpace) if (worldSpace)
{ {
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
Matrix invWorld; Matrix invWorld;
Matrix::Invert(world, invWorld); Matrix::Invert(world, invWorld);
for (auto& m : GraphInstance.NodesPose) for (auto& m : GraphInstance.NodesPose)
@@ -162,7 +162,7 @@ void AnimatedModel::GetNodeTransformation(int32 nodeIndex, Matrix& nodeTransform
if (worldSpace) if (worldSpace)
{ {
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
nodeTransformation = nodeTransformation * world; nodeTransformation = nodeTransformation * world;
} }
} }
@@ -181,7 +181,7 @@ void AnimatedModel::SetNodeTransformation(int32 nodeIndex, const Matrix& nodeTra
if (worldSpace) if (worldSpace)
{ {
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
Matrix invWorld; Matrix invWorld;
Matrix::Invert(world, invWorld); Matrix::Invert(world, invWorld);
GraphInstance.NodesPose[nodeIndex] = GraphInstance.NodesPose[nodeIndex] * invWorld; GraphInstance.NodesPose[nodeIndex] = GraphInstance.NodesPose[nodeIndex] * invWorld;
@@ -731,7 +731,9 @@ void AnimatedModel::UpdateBounds()
} }
else if (model && model->IsLoaded() && model->LODs.Count() != 0) else if (model && model->IsLoaded() && model->LODs.Count() != 0)
{ {
const BoundingBox modelBox = model->GetBox(_transform.GetWorld()); Matrix world;
GetLocalToWorldMatrix(world);
const BoundingBox modelBox = model->GetBox(world);
BoundingBox box = modelBox; BoundingBox box = modelBox;
if (GraphInstance.NodesPose.Count() != 0) if (GraphInstance.NodesPose.Count() != 0)
{ {
@@ -911,8 +913,8 @@ void AnimatedModel::Draw(RenderContext& renderContext)
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas) if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
return; // No supported return; // No supported
Matrix world; Matrix world;
const Float3 translation = _transform.Translation - renderContext.View.Origin; GetLocalToWorldMatrix(world);
Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world); renderContext.View.GetWorldMatrix(world);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world); GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
_lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.WorldPosition)); _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.WorldPosition));

View File

@@ -378,7 +378,7 @@ void Camera::UpdateCache()
// Update editor preview model cache // Update editor preview model cache
Matrix rot, tmp, world; Matrix rot, tmp, world;
_transform.GetWorld(tmp); GetLocalToWorldMatrix(tmp);
Matrix::RotationY(PI * -0.5f, rot); Matrix::RotationY(PI * -0.5f, rot);
Matrix::Multiply(rot, tmp, world); Matrix::Multiply(rot, tmp, world);

View File

@@ -467,7 +467,7 @@ void Spline::UpdateSpline()
for (int32 i = 1; i < count; i++) for (int32 i = 1; i < count; i++)
_localBounds.Merge(keyframes[i].Value.Translation); _localBounds.Merge(keyframes[i].Value.Translation);
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
BoundingBox::Transform(_localBounds, world, _box); BoundingBox::Transform(_localBounds, world, _box);
SplineUpdated(); SplineUpdated();
@@ -542,7 +542,7 @@ void Spline::OnTransformChanged()
Actor::OnTransformChanged(); Actor::OnTransformChanged();
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
BoundingBox::Transform(_localBounds, world, _box); BoundingBox::Transform(_localBounds, world, _box);
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
} }
@@ -560,7 +560,7 @@ void Spline::Initialize()
for (int32 i = 1; i < count; i++) for (int32 i = 1; i < count; i++)
_localBounds.Merge(keyframes[i].Value.Translation); _localBounds.Merge(keyframes[i].Value.Translation);
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
BoundingBox::Transform(_localBounds, world, _box); BoundingBox::Transform(_localBounds, world, _box);
} }

View File

@@ -335,8 +335,8 @@ void StaticModel::Draw(RenderContext& renderContext)
return; return;
} }
Matrix world; Matrix world;
const Float3 translation = _transform.Translation - renderContext.View.Origin; GetLocalToWorldMatrix(world);
Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world); renderContext.View.GetWorldMatrix(world);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world); GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
if (_vertexColorsDirty) if (_vertexColorsDirty)
FlushVertexColors(); FlushVertexColors();
@@ -369,8 +369,8 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch)
return; return;
const RenderContext& renderContext = renderContextBatch.GetMainContext(); const RenderContext& renderContext = renderContextBatch.GetMainContext();
Matrix world; Matrix world;
const Float3 translation = _transform.Translation - renderContext.View.Origin; GetLocalToWorldMatrix(world);
Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world); renderContext.View.GetWorldMatrix(world);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world); GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
if (_vertexColorsDirty) if (_vertexColorsDirty)
FlushVertexColors(); FlushVertexColors();

View File

@@ -233,11 +233,9 @@ void GPUParticles::Execute(GPUContext* context, ParticleEmitter* emitter, Partic
else else
{ {
Matrix worldMatrix; Matrix worldMatrix;
const Transform transform = effect->GetTransform(); effect->GetLocalToWorldMatrix(worldMatrix);
if (viewTask) if (viewTask)
viewTask->View.GetWorldMatrix(transform, worldMatrix); viewTask->View.GetWorldMatrix(worldMatrix);
else
transform.GetWorld(worldMatrix);
Matrix::Transpose(worldMatrix, cbData->WorldMatrix); Matrix::Transpose(worldMatrix, cbData->WorldMatrix);
worldMatrix.Invert(); worldMatrix.Invert();
Matrix::Transpose(worldMatrix, cbData->InvWorldMatrix); Matrix::Transpose(worldMatrix, cbData->InvWorldMatrix);

View File

@@ -847,7 +847,8 @@ void Cloth::OnPostUpdate()
if (_meshDeformation) if (_meshDeformation)
{ {
// Mark mesh as dirty // Mark mesh as dirty
const Matrix invWorld = Matrix::Invert(_transform.GetWorld()); Matrix invWorld;
GetWorldToLocalMatrix(invWorld);
BoundingBox localBounds; BoundingBox localBounds;
BoundingBox::Transform(_box, invWorld, localBounds); BoundingBox::Transform(_box, invWorld, localBounds);
_meshDeformation->Dirty(_mesh.LODIndex, _mesh.MeshIndex, MeshBufferType::Vertex0, localBounds); _meshDeformation->Dirty(_mesh.LODIndex, _mesh.MeshIndex, MeshBufferType::Vertex0, localBounds);

View File

@@ -64,7 +64,7 @@ bool cacheStaticGeometryTree(Actor* actor, ShadowsOfMordor::Builder::SceneBuildC
if (useLightmap && anyValid && entry.Scale > ZeroTolerance) if (useLightmap && anyValid && entry.Scale > ZeroTolerance)
{ {
Matrix worldMatrix; Matrix worldMatrix;
staticModel->GetTransform().GetWorld(worldMatrix); staticModel->GetLocalToWorldMatrix(worldMatrix);
entry.Box = model->GetBox(worldMatrix); entry.Box = model->GetBox(worldMatrix);
results.Add(entry); results.Add(entry);
} }

View File

@@ -125,7 +125,7 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
auto& lod = staticModel->Model->LODs[0]; auto& lod = staticModel->Model->LODs[0];
Matrix worldMatrix; Matrix worldMatrix;
staticModel->GetTransform().GetWorld(worldMatrix); staticModel->GetLocalToWorldMatrix(worldMatrix);
Matrix::Transpose(worldMatrix, shaderData.WorldMatrix); Matrix::Transpose(worldMatrix, shaderData.WorldMatrix);
shaderData.LightmapArea = staticModel->Lightmap.UVsArea; shaderData.LightmapArea = staticModel->Lightmap.UVsArea;

View File

@@ -213,7 +213,7 @@ void SpriteRender::OnTransformChanged()
const BoundingSphere localSphere(Vector3::Zero, _size.Length()); const BoundingSphere localSphere(Vector3::Zero, _size.Length());
Matrix world; Matrix world;
_transform.GetWorld(world); GetLocalToWorldMatrix(world);
BoundingSphere::Transform(localSphere, world, _sphere); BoundingSphere::Transform(localSphere, world, _sphere);
BoundingBox::FromSphere(_sphere, _box); BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1) if (_sceneRenderingKey != -1)