Node rotation/scale now transforms correctly around the pivot point

This commit is contained in:
Aruki 2017-02-10 23:55:07 -07:00
parent 511a2d8c1f
commit 568cd67994
10 changed files with 54 additions and 11 deletions

View File

@ -291,13 +291,34 @@ void CSceneNode::Rotate(const CQuaternion& rkRotation, ETransformSpace Transform
MarkTransformChanged();
}
void CSceneNode::Rotate(const CQuaternion& rkRotation, const CVector3f& rkPivot, const CQuaternion& rkPivotRotation, ETransformSpace TransformSpace)
{
Rotate(rkRotation, TransformSpace);
switch (TransformSpace)
{
case eWorldTransform:
mPosition = rkPivot + (rkRotation * (mPosition - rkPivot));
break;
case eLocalTransform:
mPosition = rkPivot + ((rkPivotRotation * rkRotation * rkPivotRotation.Inverse()) * (mPosition - rkPivot));
break;
}
MarkTransformChanged();
}
void CSceneNode::Scale(const CVector3f& rkScale)
{
// No support for stretch/skew world-space scaling; local only
mScale *= rkScale;
MarkTransformChanged();
}
void CSceneNode::Scale(const CVector3f& rkScale, const CVector3f& rkPivot)
{
mPosition = rkPivot + ((mPosition - rkPivot) * rkScale * rkScale);
Scale(rkScale);
}
void CSceneNode::ForceRecalculateTransform() const
{
_mCachedTransform = CTransform4f::skIdentity;

View File

@ -86,7 +86,9 @@ public:
// Transform
void Translate(const CVector3f& rkTranslation, ETransformSpace TransformSpace);
void Rotate(const CQuaternion& rkRotation, ETransformSpace TransformSpace);
void Rotate(const CQuaternion& rkRotation, const CVector3f& rkPivot, const CQuaternion& rkPivotRotation, ETransformSpace TransformSpace);
void Scale(const CVector3f& rkScale);
void Scale(const CVector3f& rkScale, const CVector3f& rkPivot);
const CTransform4f& Transform() const;
protected:
void MarkTransformChanged() const;

View File

@ -35,6 +35,8 @@ void CEditorApplication::InitEditor()
mpResourceBrowser = new CResourceBrowser(mpWorldEditor);
mpProjectDialog = new CProjectOverviewDialog();
connect(mpProjectDialog, SIGNAL(ActiveProjectChanged(CGameProject*)), mpResourceBrowser, SLOT(UpdateStore()));
mpProjectDialog->show();
}
void CEditorApplication::EditResource(CResourceEntry *pEntry)

View File

@ -330,14 +330,14 @@ void INodeEditor::OnGizmoMoved()
case CGizmo::eRotate:
{
CQuaternion Delta = mGizmo.DeltaRotation();
mUndoStack.push(new CRotateNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, Delta, mRotateSpace));
mUndoStack.push(new CRotateNodeCommand(this, mpSelection->SelectedNodeList(), true, mGizmo.Position(), mGizmo.Rotation(), Delta, mRotateSpace));
break;
}
case CGizmo::eScale:
{
CVector3f Delta = mGizmo.DeltaScale();
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, Delta));
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), true, mGizmo.Position(), Delta));
break;
}
}

View File

@ -9,7 +9,15 @@ CRotateNodeCommand::CRotateNodeCommand()
{
}
CRotateNodeCommand::CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& rkNodes, const CVector3f& /*rkPivot*/, const CQuaternion& rkDelta, ETransformSpace TransformSpace)
CRotateNodeCommand::CRotateNodeCommand(
INodeEditor *pEditor,
const QList<CSceneNode*>& rkNodes,
bool UsePivot,
const CVector3f& rkPivot,
const CQuaternion& rkPivotRotation,
const CQuaternion& rkDelta,
ETransformSpace TransformSpace
)
: IUndoCommand("Rotate"),
mpEditor(pEditor),
mCommandEnded(false)
@ -22,7 +30,12 @@ CRotateNodeCommand::CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneN
Rotate.pNode = pNode;
Rotate.InitialPos = pNode->LocalPosition();
Rotate.InitialRot = pNode->LocalRotation();
pNode->Rotate(rkDelta, TransformSpace);
if (UsePivot)
pNode->Rotate(rkDelta, rkPivot, rkPivotRotation, TransformSpace);
else
pNode->Rotate(rkDelta, TransformSpace);
Rotate.NewPos = pNode->LocalPosition();
Rotate.NewRot = pNode->LocalRotation();
mNodeList.push_back(Rotate);

View File

@ -23,7 +23,7 @@ class CRotateNodeCommand : public IUndoCommand
public:
CRotateNodeCommand();
CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& rkNodes, const CVector3f& rkPivot, const CQuaternion& rkDelta, ETransformSpace TransformSpace);
CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& rkNodes, bool UsePivot, const CVector3f& rkPivot, const CQuaternion& rkPivotRotation, const CQuaternion& rkDelta, ETransformSpace TransformSpace);
~CRotateNodeCommand();
int id() const;
bool mergeWith(const QUndoCommand *pkOther);

View File

@ -9,7 +9,7 @@ CScaleNodeCommand::CScaleNodeCommand()
{
}
CScaleNodeCommand::CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& rkNodes, const CVector3f& /*rkPivot*/, const CVector3f& rkDelta)
CScaleNodeCommand::CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& rkNodes, bool UsePivot, const CVector3f& rkPivot, const CVector3f& rkDelta)
: IUndoCommand("Scale"),
mpEditor(pEditor),
mCommandEnded(false)
@ -22,6 +22,12 @@ CScaleNodeCommand::CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNod
Scale.pNode = pNode;
Scale.InitialPos = pNode->LocalPosition();
Scale.InitialScale = pNode->LocalScale();
if (UsePivot)
pNode->Scale(rkDelta, rkPivot);
else
pNode->Scale(rkDelta);
pNode->Scale(rkDelta);
Scale.NewPos = pNode->LocalPosition();
Scale.NewScale = pNode->LocalScale();

View File

@ -23,7 +23,7 @@ class CScaleNodeCommand : public IUndoCommand
public:
CScaleNodeCommand();
CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& rkNodes, const CVector3f& rkPivot, const CVector3f& rkDelta);
CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& rkNodes, bool UsePivot, const CVector3f& rkPivot, const CVector3f& rkDelta);
~CScaleNodeCommand();
int id() const;
bool mergeWith(const QUndoCommand *pkOther);

View File

@ -921,14 +921,14 @@ void CWorldEditor::OnTransformSpinBoxModified(CVector3f Value)
case CGizmo::eRotate:
{
CQuaternion Delta = CQuaternion::FromEuler(Value) * mpSelection->Front()->AbsoluteRotation().Inverse();
mUndoStack.push(new CRotateNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, Delta, mRotateSpace));
mUndoStack.push(new CRotateNodeCommand(this, mpSelection->SelectedNodeList(), true, mGizmo.Position(), mGizmo.Rotation(), Delta, mRotateSpace));
break;
}
case CGizmo::eScale:
{
CVector3f Delta = Value / mpSelection->Front()->AbsoluteScale();
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, Delta));
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), true, mGizmo.Position(), Delta));
break;
}
}

View File

@ -59,6 +59,5 @@ int main(int argc, char *argv[])
// Execute application
App.InitEditor();
App.ProjectDialog()->show();
return App.exec();
}