Node rotation/scale now transforms correctly around the pivot point
This commit is contained in:
parent
511a2d8c1f
commit
568cd67994
|
@ -291,13 +291,34 @@ void CSceneNode::Rotate(const CQuaternion& rkRotation, ETransformSpace Transform
|
||||||
MarkTransformChanged();
|
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)
|
void CSceneNode::Scale(const CVector3f& rkScale)
|
||||||
{
|
{
|
||||||
// No support for stretch/skew world-space scaling; local only
|
|
||||||
mScale *= rkScale;
|
mScale *= rkScale;
|
||||||
MarkTransformChanged();
|
MarkTransformChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSceneNode::Scale(const CVector3f& rkScale, const CVector3f& rkPivot)
|
||||||
|
{
|
||||||
|
mPosition = rkPivot + ((mPosition - rkPivot) * rkScale * rkScale);
|
||||||
|
Scale(rkScale);
|
||||||
|
}
|
||||||
|
|
||||||
void CSceneNode::ForceRecalculateTransform() const
|
void CSceneNode::ForceRecalculateTransform() const
|
||||||
{
|
{
|
||||||
_mCachedTransform = CTransform4f::skIdentity;
|
_mCachedTransform = CTransform4f::skIdentity;
|
||||||
|
|
|
@ -86,7 +86,9 @@ public:
|
||||||
// Transform
|
// Transform
|
||||||
void Translate(const CVector3f& rkTranslation, ETransformSpace TransformSpace);
|
void Translate(const CVector3f& rkTranslation, ETransformSpace TransformSpace);
|
||||||
void Rotate(const CQuaternion& rkRotation, 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);
|
||||||
|
void Scale(const CVector3f& rkScale, const CVector3f& rkPivot);
|
||||||
const CTransform4f& Transform() const;
|
const CTransform4f& Transform() const;
|
||||||
protected:
|
protected:
|
||||||
void MarkTransformChanged() const;
|
void MarkTransformChanged() const;
|
||||||
|
|
|
@ -35,6 +35,8 @@ void CEditorApplication::InitEditor()
|
||||||
mpResourceBrowser = new CResourceBrowser(mpWorldEditor);
|
mpResourceBrowser = new CResourceBrowser(mpWorldEditor);
|
||||||
mpProjectDialog = new CProjectOverviewDialog();
|
mpProjectDialog = new CProjectOverviewDialog();
|
||||||
connect(mpProjectDialog, SIGNAL(ActiveProjectChanged(CGameProject*)), mpResourceBrowser, SLOT(UpdateStore()));
|
connect(mpProjectDialog, SIGNAL(ActiveProjectChanged(CGameProject*)), mpResourceBrowser, SLOT(UpdateStore()));
|
||||||
|
|
||||||
|
mpProjectDialog->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorApplication::EditResource(CResourceEntry *pEntry)
|
void CEditorApplication::EditResource(CResourceEntry *pEntry)
|
||||||
|
|
|
@ -330,14 +330,14 @@ void INodeEditor::OnGizmoMoved()
|
||||||
case CGizmo::eRotate:
|
case CGizmo::eRotate:
|
||||||
{
|
{
|
||||||
CQuaternion Delta = mGizmo.DeltaRotation();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CGizmo::eScale:
|
case CGizmo::eScale:
|
||||||
{
|
{
|
||||||
CVector3f Delta = mGizmo.DeltaScale();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"),
|
: IUndoCommand("Rotate"),
|
||||||
mpEditor(pEditor),
|
mpEditor(pEditor),
|
||||||
mCommandEnded(false)
|
mCommandEnded(false)
|
||||||
|
@ -22,7 +30,12 @@ CRotateNodeCommand::CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneN
|
||||||
Rotate.pNode = pNode;
|
Rotate.pNode = pNode;
|
||||||
Rotate.InitialPos = pNode->LocalPosition();
|
Rotate.InitialPos = pNode->LocalPosition();
|
||||||
Rotate.InitialRot = pNode->LocalRotation();
|
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.NewPos = pNode->LocalPosition();
|
||||||
Rotate.NewRot = pNode->LocalRotation();
|
Rotate.NewRot = pNode->LocalRotation();
|
||||||
mNodeList.push_back(Rotate);
|
mNodeList.push_back(Rotate);
|
||||||
|
|
|
@ -23,7 +23,7 @@ class CRotateNodeCommand : public IUndoCommand
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CRotateNodeCommand();
|
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();
|
~CRotateNodeCommand();
|
||||||
int id() const;
|
int id() const;
|
||||||
bool mergeWith(const QUndoCommand *pkOther);
|
bool mergeWith(const QUndoCommand *pkOther);
|
||||||
|
|
|
@ -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"),
|
: IUndoCommand("Scale"),
|
||||||
mpEditor(pEditor),
|
mpEditor(pEditor),
|
||||||
mCommandEnded(false)
|
mCommandEnded(false)
|
||||||
|
@ -22,6 +22,12 @@ CScaleNodeCommand::CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNod
|
||||||
Scale.pNode = pNode;
|
Scale.pNode = pNode;
|
||||||
Scale.InitialPos = pNode->LocalPosition();
|
Scale.InitialPos = pNode->LocalPosition();
|
||||||
Scale.InitialScale = pNode->LocalScale();
|
Scale.InitialScale = pNode->LocalScale();
|
||||||
|
|
||||||
|
if (UsePivot)
|
||||||
|
pNode->Scale(rkDelta, rkPivot);
|
||||||
|
else
|
||||||
|
pNode->Scale(rkDelta);
|
||||||
|
|
||||||
pNode->Scale(rkDelta);
|
pNode->Scale(rkDelta);
|
||||||
Scale.NewPos = pNode->LocalPosition();
|
Scale.NewPos = pNode->LocalPosition();
|
||||||
Scale.NewScale = pNode->LocalScale();
|
Scale.NewScale = pNode->LocalScale();
|
||||||
|
|
|
@ -23,7 +23,7 @@ class CScaleNodeCommand : public IUndoCommand
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CScaleNodeCommand();
|
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();
|
~CScaleNodeCommand();
|
||||||
int id() const;
|
int id() const;
|
||||||
bool mergeWith(const QUndoCommand *pkOther);
|
bool mergeWith(const QUndoCommand *pkOther);
|
||||||
|
|
|
@ -921,14 +921,14 @@ void CWorldEditor::OnTransformSpinBoxModified(CVector3f Value)
|
||||||
case CGizmo::eRotate:
|
case CGizmo::eRotate:
|
||||||
{
|
{
|
||||||
CQuaternion Delta = CQuaternion::FromEuler(Value) * mpSelection->Front()->AbsoluteRotation().Inverse();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CGizmo::eScale:
|
case CGizmo::eScale:
|
||||||
{
|
{
|
||||||
CVector3f Delta = Value / mpSelection->Front()->AbsoluteScale();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,5 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
// Execute application
|
// Execute application
|
||||||
App.InitEditor();
|
App.InitEditor();
|
||||||
App.ProjectDialog()->show();
|
|
||||||
return App.exec();
|
return App.exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue