Translation gizmo transform functionality implemented
This commit is contained in:
parent
08dbdb337a
commit
63c8351dcf
|
@ -0,0 +1,44 @@
|
||||||
|
#include "CPlane.h"
|
||||||
|
|
||||||
|
CPlane::CPlane()
|
||||||
|
{
|
||||||
|
mNormal = CVector3f::skUp;
|
||||||
|
mDist = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPlane::CPlane(const CVector3f& normal, float dist)
|
||||||
|
{
|
||||||
|
mNormal = normal;
|
||||||
|
mDist = dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPlane::CPlane(const CVector3f& normal, const CVector3f& origin)
|
||||||
|
{
|
||||||
|
Redefine(normal, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlane::Redefine(const CVector3f& normal, const CVector3f& origin)
|
||||||
|
{
|
||||||
|
mNormal = normal;
|
||||||
|
mDist = -normal.Dot(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector3f CPlane::Normal() const
|
||||||
|
{
|
||||||
|
return mNormal;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CPlane::Dist() const
|
||||||
|
{
|
||||||
|
return mDist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlane::SetNormal(const CVector3f& normal)
|
||||||
|
{
|
||||||
|
mNormal = normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlane::SetDist(float dist)
|
||||||
|
{
|
||||||
|
mDist = dist;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef CPLANE_H
|
||||||
|
#define CPLANE_H
|
||||||
|
|
||||||
|
#include "CVector3f.h"
|
||||||
|
|
||||||
|
class CPlane
|
||||||
|
{
|
||||||
|
CVector3f mNormal;
|
||||||
|
float mDist;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CPlane();
|
||||||
|
CPlane(const CVector3f& normal, float dist);
|
||||||
|
CPlane(const CVector3f& normal, const CVector3f& origin);
|
||||||
|
|
||||||
|
void Redefine(const CVector3f& normal, const CVector3f& origin);
|
||||||
|
CVector3f Normal() const;
|
||||||
|
float Dist() const;
|
||||||
|
void SetNormal(const CVector3f& normal);
|
||||||
|
void SetDist(float dist);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPLANE_H
|
|
@ -18,6 +18,47 @@ CQuaternion::CQuaternion(float _x, float _y, float _z, float _w)
|
||||||
w = _w;
|
w = _w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CVector3f CQuaternion::XAxis()
|
||||||
|
{
|
||||||
|
return (*this * CVector3f::skUnitX);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector3f CQuaternion::YAxis()
|
||||||
|
{
|
||||||
|
return (*this * CVector3f::skUnitY);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector3f CQuaternion::ZAxis()
|
||||||
|
{
|
||||||
|
return (*this * CVector3f::skUnitZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
CQuaternion CQuaternion::Inverse()
|
||||||
|
{
|
||||||
|
float fNorm = (w * w) + (x * x) + (y * y) + (z * z);
|
||||||
|
|
||||||
|
if (fNorm > 0.f)
|
||||||
|
{
|
||||||
|
float fInvNorm = 1.f / fNorm;
|
||||||
|
return CQuaternion(-x * fInvNorm, -y * fInvNorm, -z * fInvNorm, w * fInvNorm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return CQuaternion::skZero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ OPERATORS ************
|
||||||
|
CVector3f CQuaternion::operator*(const CVector3f& vec) const
|
||||||
|
{
|
||||||
|
CVector3f uv, uuv;
|
||||||
|
CVector3f qvec(x, y, z);
|
||||||
|
uv = qvec.Cross(vec);
|
||||||
|
uuv = qvec.Cross(uv);
|
||||||
|
uv *= (2.0f * w);
|
||||||
|
uuv *= 2.0f;
|
||||||
|
|
||||||
|
return vec + uv + uuv;
|
||||||
|
}
|
||||||
|
|
||||||
CQuaternion CQuaternion::operator*(const CQuaternion& other) const
|
CQuaternion CQuaternion::operator*(const CQuaternion& other) const
|
||||||
{
|
{
|
||||||
CQuaternion out;
|
CQuaternion out;
|
||||||
|
@ -84,3 +125,4 @@ CQuaternion CQuaternion::FromAxisAngle(float angle, CVector3f axis)
|
||||||
}
|
}
|
||||||
|
|
||||||
CQuaternion CQuaternion::skIdentity = CQuaternion(0.f, 0.f, 0.f, 1.f);
|
CQuaternion CQuaternion::skIdentity = CQuaternion(0.f, 0.f, 0.f, 1.f);
|
||||||
|
CQuaternion CQuaternion::skZero = CQuaternion(0.f, 0.f, 0.f, 0.f);
|
||||||
|
|
|
@ -11,7 +11,13 @@ public:
|
||||||
CQuaternion();
|
CQuaternion();
|
||||||
CQuaternion(float _x, float _y, float _z, float _w);
|
CQuaternion(float _x, float _y, float _z, float _w);
|
||||||
|
|
||||||
|
CVector3f XAxis();
|
||||||
|
CVector3f YAxis();
|
||||||
|
CVector3f ZAxis();
|
||||||
|
CQuaternion Inverse();
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
|
CVector3f operator*(const CVector3f& vec) const;
|
||||||
CQuaternion operator*(const CQuaternion& other) const;
|
CQuaternion operator*(const CQuaternion& other) const;
|
||||||
void operator *= (const CQuaternion& other);
|
void operator *= (const CQuaternion& other);
|
||||||
|
|
||||||
|
@ -20,6 +26,7 @@ public:
|
||||||
static CQuaternion FromAxisAngle(float angle, CVector3f axis);
|
static CQuaternion FromAxisAngle(float angle, CVector3f axis);
|
||||||
|
|
||||||
static CQuaternion skIdentity;
|
static CQuaternion skIdentity;
|
||||||
|
static CQuaternion skZero;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CQUATERNION_H
|
#endif // CQUATERNION_H
|
||||||
|
|
|
@ -279,12 +279,15 @@ const float& CVector3f::operator[](long index) const
|
||||||
const CVector3f CVector3f::skZero = CVector3f(0.f);
|
const CVector3f CVector3f::skZero = CVector3f(0.f);
|
||||||
const CVector3f CVector3f::skOne = CVector3f(1.f);
|
const CVector3f CVector3f::skOne = CVector3f(1.f);
|
||||||
const CVector3f CVector3f::skInfinite = CVector3f(FLT_MAX);
|
const CVector3f CVector3f::skInfinite = CVector3f(FLT_MAX);
|
||||||
const CVector3f CVector3f::skForward = CVector3f(0.f, 1.f, 0.f);
|
const CVector3f CVector3f::skUnitX = CVector3f(1.f, 0.f, 0.f);
|
||||||
const CVector3f CVector3f::skBack = CVector3f(0.f, -1.f, 0.f);
|
const CVector3f CVector3f::skUnitY = CVector3f(0.f, 1.f, 0.f);
|
||||||
const CVector3f CVector3f::skRight = CVector3f( 1.f, 0.f, 0.f);
|
const CVector3f CVector3f::skUnitZ = CVector3f(0.f, 0.f, 1.f);
|
||||||
const CVector3f CVector3f::skLeft = CVector3f(-1.f, 0.f, 0.f);
|
const CVector3f CVector3f::skRight = CVector3f::skUnitX;
|
||||||
const CVector3f CVector3f::skUp = CVector3f(0.f, 0.f, 1.f);
|
const CVector3f CVector3f::skLeft = -CVector3f::skUnitX;
|
||||||
const CVector3f CVector3f::skDown = CVector3f(0.f, 0.f, -1.f);
|
const CVector3f CVector3f::skForward = CVector3f::skUnitY;
|
||||||
|
const CVector3f CVector3f::skBack = -CVector3f::skUnitY;
|
||||||
|
const CVector3f CVector3f::skUp = CVector3f::skUnitZ;
|
||||||
|
const CVector3f CVector3f::skDown = -CVector3f::skUnitZ;
|
||||||
|
|
||||||
// ************ OTHER ************
|
// ************ OTHER ************
|
||||||
std::ostream& operator<<(std::ostream& o, const CVector3f& Vector)
|
std::ostream& operator<<(std::ostream& o, const CVector3f& Vector)
|
||||||
|
|
|
@ -75,10 +75,13 @@ public:
|
||||||
static const CVector3f skZero;
|
static const CVector3f skZero;
|
||||||
static const CVector3f skOne;
|
static const CVector3f skOne;
|
||||||
static const CVector3f skInfinite;
|
static const CVector3f skInfinite;
|
||||||
static const CVector3f skForward;
|
static const CVector3f skUnitX;
|
||||||
static const CVector3f skBack;
|
static const CVector3f skUnitY;
|
||||||
|
static const CVector3f skUnitZ;
|
||||||
static const CVector3f skRight;
|
static const CVector3f skRight;
|
||||||
static const CVector3f skLeft;
|
static const CVector3f skLeft;
|
||||||
|
static const CVector3f skForward;
|
||||||
|
static const CVector3f skBack;
|
||||||
static const CVector3f skUp;
|
static const CVector3f skUp;
|
||||||
static const CVector3f skDown;
|
static const CVector3f skDown;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef ETRANSFORMSPACE
|
||||||
|
#define ETRANSFORMSPACE
|
||||||
|
|
||||||
|
enum ETransformSpace
|
||||||
|
{
|
||||||
|
eWorldTransform,
|
||||||
|
eLocalTransform
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ETRANSFORMSPACE
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
|
|
||||||
|
float Abs(float v)
|
||||||
|
{
|
||||||
|
return fabs(v);
|
||||||
|
}
|
||||||
|
|
||||||
float Pow(float Base, float Exponent)
|
float Pow(float Base, float Exponent)
|
||||||
{
|
{
|
||||||
return pow(Base, Exponent);
|
return pow(Base, Exponent);
|
||||||
|
@ -15,6 +20,23 @@ float Distance(const CVector3f& A, const CVector3f& B)
|
||||||
Pow(B.z - A.z, 2.f) );
|
Pow(B.z - A.z, 2.f) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane)
|
||||||
|
{
|
||||||
|
// Code based on ray/plane intersect code from Ogre
|
||||||
|
// https://bitbucket.org/sinbad/ogre/src/197116fd2ac62c57cdeed1666f9866c3dddd4289/OgreMain/src/OgreMath.cpp?at=default#OgreMath.cpp-350
|
||||||
|
|
||||||
|
// Are ray and plane parallel?
|
||||||
|
float denom = plane.Normal().Dot(ray.Direction());
|
||||||
|
|
||||||
|
if (Abs(denom) < FLT_EPSILON)
|
||||||
|
return std::pair<bool,float>(false, 0.f);
|
||||||
|
|
||||||
|
// Not parallel
|
||||||
|
float nom = plane.Normal().Dot(ray.Origin()) + plane.Dist();
|
||||||
|
float t = -(nom / denom);
|
||||||
|
return std::pair<bool,float>(t >= 0.f, t);
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box)
|
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box)
|
||||||
{
|
{
|
||||||
// Code slightly modified from Ogre
|
// Code slightly modified from Ogre
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "CAABox.h"
|
#include "CAABox.h"
|
||||||
#include "CRay.h"
|
#include "CRay.h"
|
||||||
|
#include "CPlane.h"
|
||||||
#include "CVector3f.h"
|
#include "CVector3f.h"
|
||||||
#include "SRayIntersection.h"
|
#include "SRayIntersection.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -10,10 +11,14 @@
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
|
|
||||||
|
float Abs(float v);
|
||||||
|
|
||||||
float Pow(float Base, float Exponent);
|
float Pow(float Base, float Exponent);
|
||||||
|
|
||||||
float Distance(const CVector3f& A, const CVector3f& B);
|
float Distance(const CVector3f& A, const CVector3f& B);
|
||||||
|
|
||||||
|
std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane);
|
||||||
|
|
||||||
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box);
|
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box);
|
||||||
|
|
||||||
std::pair<bool,float> RayLineIntersection(const CRay& ray, const CVector3f& pointA,
|
std::pair<bool,float> RayLineIntersection(const CRay& ray, const CVector3f& pointA,
|
||||||
|
|
|
@ -140,10 +140,6 @@ void CRenderer::RenderBuckets(CCamera& Camera)
|
||||||
mTransparentBucket.Sort(Camera);
|
mTransparentBucket.Sort(Camera);
|
||||||
mTransparentBucket.Draw(mOptions);
|
mTransparentBucket.Draw(mOptions);
|
||||||
mTransparentBucket.Clear();
|
mTransparentBucket.Clear();
|
||||||
|
|
||||||
// Clear depth buffer to enable more rendering passes
|
|
||||||
glDepthMask(GL_TRUE);
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::RenderBloom()
|
void CRenderer::RenderBloom()
|
||||||
|
@ -331,6 +327,12 @@ void CRenderer::EndFrame()
|
||||||
gDrawCount = 0;
|
gDrawCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRenderer::ClearDepthBuffer()
|
||||||
|
{
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
// ************ PRIVATE ************
|
// ************ PRIVATE ************
|
||||||
void CRenderer::InitFramebuffer()
|
void CRenderer::InitFramebuffer()
|
||||||
{
|
{
|
||||||
|
|
|
@ -72,6 +72,7 @@ public:
|
||||||
void AddTransparentMesh(IRenderable *pRenderable, u32 AssetID, CAABox& AABox, ERenderCommand Command);
|
void AddTransparentMesh(IRenderable *pRenderable, u32 AssetID, CAABox& AABox, ERenderCommand Command);
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
void EndFrame();
|
void EndFrame();
|
||||||
|
void ClearDepthBuffer();
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -157,7 +157,6 @@ void CSceneManager::SetActiveArea(CGameArea* _area)
|
||||||
{
|
{
|
||||||
CScriptObject *pObj = pGenLayer->ObjectByIndex(o);
|
CScriptObject *pObj = pGenLayer->ObjectByIndex(o);
|
||||||
CScriptNode *Node = AddScriptObject(pObj);
|
CScriptNode *Node = AddScriptObject(pObj);
|
||||||
Node->BuildLightList(mpArea);
|
|
||||||
|
|
||||||
// Add to map
|
// Add to map
|
||||||
mScriptNodeMap[pObj->InstanceID()] = Node;
|
mScriptNodeMap[pObj->InstanceID()] = Node;
|
||||||
|
@ -165,9 +164,12 @@ void CSceneManager::SetActiveArea(CGameArea* _area)
|
||||||
}
|
}
|
||||||
PickEnvironmentObjects();
|
PickEnvironmentObjects();
|
||||||
|
|
||||||
// Ensure script nodes have valid positions
|
// Ensure script nodes have valid positions + build light lists
|
||||||
for (auto it = mScriptNodeMap.begin(); it != mScriptNodeMap.end(); it++)
|
for (auto it = mScriptNodeMap.begin(); it != mScriptNodeMap.end(); it++)
|
||||||
|
{
|
||||||
it->second->GeneratePosition();
|
it->second->GeneratePosition();
|
||||||
|
it->second->BuildLightList(mpArea);
|
||||||
|
}
|
||||||
|
|
||||||
u32 NumLightLayers = mpArea->GetLightLayerCount();
|
u32 NumLightLayers = mpArea->GetLightLayerCount();
|
||||||
CGraphics::sAreaAmbientColor = CColor::skBlack;
|
CGraphics::sAreaAmbientColor = CColor::skBlack;
|
||||||
|
|
|
@ -134,7 +134,8 @@ SOURCES += \
|
||||||
UI/WScanPreviewPanel.cpp \
|
UI/WScanPreviewPanel.cpp \
|
||||||
UI/WIntegralSpinBox.cpp \
|
UI/WIntegralSpinBox.cpp \
|
||||||
UI/CAboutDialog.cpp \
|
UI/CAboutDialog.cpp \
|
||||||
UI/CGizmo.cpp
|
UI/CGizmo.cpp \
|
||||||
|
Common/CPlane.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Common/AnimUtil.h \
|
Common/AnimUtil.h \
|
||||||
|
@ -283,7 +284,9 @@ HEADERS += \
|
||||||
UI/CAboutDialog.h \
|
UI/CAboutDialog.h \
|
||||||
UI/CGizmo.h \
|
UI/CGizmo.h \
|
||||||
Core/IRenderable.h \
|
Core/IRenderable.h \
|
||||||
Core/SRenderablePtr.h
|
Core/SRenderablePtr.h \
|
||||||
|
Common/ETransformSpace.h \
|
||||||
|
Common/CPlane.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
UI/CWorldEditorWindow.ui \
|
UI/CWorldEditorWindow.ui \
|
||||||
|
|
|
@ -185,15 +185,29 @@ void CSceneNode::DrawBoundingBox()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ TRANSFORM ************
|
// ************ TRANSFORM ************
|
||||||
void CSceneNode::Translate(const CVector3f& Translation)
|
void CSceneNode::Translate(const CVector3f& translation, ETransformSpace transformSpace)
|
||||||
{
|
{
|
||||||
mPosition += Translation;
|
switch (transformSpace)
|
||||||
|
{
|
||||||
|
case eWorldTransform:
|
||||||
|
mPosition += translation;
|
||||||
|
break;
|
||||||
|
case eLocalTransform:
|
||||||
|
mPosition += mRotation * translation;
|
||||||
|
break;
|
||||||
|
}
|
||||||
MarkTransformChanged();
|
MarkTransformChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneNode::Scale(const CVector3f& Scale)
|
void CSceneNode::Rotate(const CQuaternion& rotation, ETransformSpace transformSpace)
|
||||||
{
|
{
|
||||||
mScale *= Scale;
|
mRotation *= rotation;
|
||||||
|
MarkTransformChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSceneNode::Scale(const CVector3f& scale, ETransformSpace transformSpace)
|
||||||
|
{
|
||||||
|
mScale *= scale;
|
||||||
MarkTransformChanged();
|
MarkTransformChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +223,9 @@ void CSceneNode::UpdateTransform()
|
||||||
void CSceneNode::ForceRecalculateTransform()
|
void CSceneNode::ForceRecalculateTransform()
|
||||||
{
|
{
|
||||||
_mCachedTransform = CTransform4f::skIdentity;
|
_mCachedTransform = CTransform4f::skIdentity;
|
||||||
_mCachedTransform.Scale(GetAbsoluteScale());
|
_mCachedTransform.Scale(AbsoluteScale());
|
||||||
_mCachedTransform.Rotate(GetAbsoluteRotation());
|
_mCachedTransform.Rotate(AbsoluteRotation());
|
||||||
_mCachedTransform.Translate(GetAbsolutePosition());
|
_mCachedTransform.Translate(AbsolutePosition());
|
||||||
_mCachedAABox = mLocalAABox.Transformed(_mCachedTransform);
|
_mCachedAABox = mLocalAABox.Transformed(_mCachedTransform);
|
||||||
|
|
||||||
// Sync with children - only needed if caller hasn't marked transform changed already
|
// Sync with children - only needed if caller hasn't marked transform changed already
|
||||||
|
@ -259,47 +273,47 @@ CSceneManager* CSceneNode::Scene()
|
||||||
return mpScene;
|
return mpScene;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CSceneNode::GetPosition() const
|
CVector3f CSceneNode::LocalPosition() const
|
||||||
{
|
{
|
||||||
return mPosition;
|
return mPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CSceneNode::GetAbsolutePosition() const
|
CVector3f CSceneNode::AbsolutePosition() const
|
||||||
{
|
{
|
||||||
CVector3f ret = mPosition;
|
CVector3f ret = mPosition;
|
||||||
|
|
||||||
if ((mpParent) && (InheritsPosition()))
|
if ((mpParent) && (InheritsPosition()))
|
||||||
ret += mpParent->GetAbsolutePosition();
|
ret += mpParent->AbsolutePosition();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CQuaternion CSceneNode::GetRotation() const
|
CQuaternion CSceneNode::LocalRotation() const
|
||||||
{
|
{
|
||||||
return mRotation;
|
return mRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
CQuaternion CSceneNode::GetAbsoluteRotation() const
|
CQuaternion CSceneNode::AbsoluteRotation() const
|
||||||
{
|
{
|
||||||
CQuaternion ret = mRotation;
|
CQuaternion ret = mRotation;
|
||||||
|
|
||||||
if ((mpParent) && (InheritsRotation()))
|
if ((mpParent) && (InheritsRotation()))
|
||||||
ret *= mpParent->GetAbsoluteRotation();
|
ret *= mpParent->AbsoluteRotation();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CSceneNode::GetScale() const
|
CVector3f CSceneNode::LocalScale() const
|
||||||
{
|
{
|
||||||
return mScale;
|
return mScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CSceneNode::GetAbsoluteScale() const
|
CVector3f CSceneNode::AbsoluteScale() const
|
||||||
{
|
{
|
||||||
CVector3f ret = mScale;
|
CVector3f ret = mScale;
|
||||||
|
|
||||||
if ((mpParent) && (InheritsScale()))
|
if ((mpParent) && (InheritsScale()))
|
||||||
ret *= mpParent->GetAbsoluteScale();
|
ret *= mpParent->AbsoluteScale();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
|
|
||||||
#include <Core/IRenderable.h>
|
#include <Core/IRenderable.h>
|
||||||
#include "ENodeType.h"
|
#include "ENodeType.h"
|
||||||
#include <Common/CVector3f.h>
|
|
||||||
#include <Common/CQuaternion.h>
|
|
||||||
#include <Common/CAABox.h>
|
#include <Common/CAABox.h>
|
||||||
|
#include <Common/CQuaternion.h>
|
||||||
#include <Common/CRay.h>
|
#include <Common/CRay.h>
|
||||||
#include <Common/CRayCollisionTester.h>
|
#include <Common/CRayCollisionTester.h>
|
||||||
#include <Common/types.h>
|
|
||||||
#include <Common/CTransform4f.h>
|
#include <Common/CTransform4f.h>
|
||||||
|
#include <Common/CVector3f.h>
|
||||||
|
#include <Common/ETransformSpace.h>
|
||||||
|
#include <Common/types.h>
|
||||||
#include <Core/ERenderOptions.h>
|
#include <Core/ERenderOptions.h>
|
||||||
#include <Resource/CLight.h>
|
#include <Resource/CLight.h>
|
||||||
#include <Resource/CGameArea.h>
|
#include <Resource/CGameArea.h>
|
||||||
|
@ -68,8 +69,9 @@ public:
|
||||||
void DrawBoundingBox();
|
void DrawBoundingBox();
|
||||||
|
|
||||||
// Transform
|
// Transform
|
||||||
void Translate(const CVector3f& Translation);
|
void Translate(const CVector3f& translation, ETransformSpace transformSpace);
|
||||||
void Scale(const CVector3f& Scale);
|
void Rotate(const CQuaternion& rotation, ETransformSpace transformSpace);
|
||||||
|
void Scale(const CVector3f& scale, ETransformSpace transformSpace);
|
||||||
void UpdateTransform();
|
void UpdateTransform();
|
||||||
void ForceRecalculateTransform();
|
void ForceRecalculateTransform();
|
||||||
void MarkTransformChanged();
|
void MarkTransformChanged();
|
||||||
|
@ -79,12 +81,12 @@ public:
|
||||||
std::string Name() const;
|
std::string Name() const;
|
||||||
CSceneNode* Parent() const;
|
CSceneNode* Parent() const;
|
||||||
CSceneManager* Scene();
|
CSceneManager* Scene();
|
||||||
CVector3f GetPosition() const;
|
CVector3f LocalPosition() const;
|
||||||
CVector3f GetAbsolutePosition() const;
|
CVector3f AbsolutePosition() const;
|
||||||
CQuaternion GetRotation() const;
|
CQuaternion LocalRotation() const;
|
||||||
CQuaternion GetAbsoluteRotation() const;
|
CQuaternion AbsoluteRotation() const;
|
||||||
CVector3f GetScale() const;
|
CVector3f LocalScale() const;
|
||||||
CVector3f GetAbsoluteScale() const;
|
CVector3f AbsoluteScale() const;
|
||||||
CAABox AABox();
|
CAABox AABox();
|
||||||
CVector3f CenterPoint();
|
CVector3f CenterPoint();
|
||||||
bool MarkedVisible() const;
|
bool MarkedVisible() const;
|
||||||
|
|
|
@ -45,7 +45,7 @@ CScriptNode::CScriptNode(CSceneManager *pScene, CSceneNode *pParent, CScriptObje
|
||||||
{
|
{
|
||||||
mpVolumePreviewNode = new CModelNode(pScene, this, pVolumeModel);
|
mpVolumePreviewNode = new CModelNode(pScene, this, pVolumeModel);
|
||||||
mpVolumePreviewNode->SetInheritance(true, (VolumeShape == 1), false);
|
mpVolumePreviewNode->SetInheritance(true, (VolumeShape == 1), false);
|
||||||
mpVolumePreviewNode->Scale(mpInstance->GetVolume());
|
mpVolumePreviewNode->Scale(mpInstance->GetVolume(), eWorldTransform);
|
||||||
mpVolumePreviewNode->ForceAlphaEnabled(true);
|
mpVolumePreviewNode->ForceAlphaEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,7 @@ void CScriptNode::GeneratePosition()
|
||||||
const SLink& link = (mpInstance->NumInLinks() > 0 ? mpInstance->InLink(0) : mpInstance->OutLink(0));
|
const SLink& link = (mpInstance->NumInLinks() > 0 ? mpInstance->InLink(0) : mpInstance->OutLink(0));
|
||||||
CScriptNode *pNode = mpScene->ScriptNodeByID(link.ObjectID);
|
CScriptNode *pNode = mpScene->ScriptNodeByID(link.ObjectID);
|
||||||
pNode->GeneratePosition();
|
pNode->GeneratePosition();
|
||||||
mPosition = pNode->GetAbsolutePosition();
|
mPosition = pNode->AbsolutePosition();
|
||||||
mPosition.z += (pNode->AABox().Size().z / 2.f);
|
mPosition.z += (pNode->AABox().Size().z / 2.f);
|
||||||
mPosition.z += (AABox().Size().z / 2.f);
|
mPosition.z += (AABox().Size().z / 2.f);
|
||||||
mPosition.z += 2.f;
|
mPosition.z += 2.f;
|
||||||
|
|
|
@ -105,24 +105,31 @@ void CEditorGLWidget::mousePressEvent(QMouseEvent *pEvent)
|
||||||
|
|
||||||
// Left click only activates if mouse input is inactive to prevent the user from
|
// Left click only activates if mouse input is inactive to prevent the user from
|
||||||
// clicking on things and creating selection rectangles while the cursor is hidden
|
// clicking on things and creating selection rectangles while the cursor is hidden
|
||||||
else if (pEvent->button() == Qt::LeftButton)
|
else
|
||||||
|
{
|
||||||
|
if (pEvent->button() == Qt::LeftButton)
|
||||||
mButtonsPressed |= eLeftButton;
|
mButtonsPressed |= eLeftButton;
|
||||||
|
|
||||||
|
emit MouseClick(pEvent);
|
||||||
|
}
|
||||||
|
|
||||||
mLastMousePos = pEvent->globalPos();
|
mLastMousePos = pEvent->globalPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::mouseReleaseEvent(QMouseEvent *pEvent)
|
void CEditorGLWidget::mouseReleaseEvent(QMouseEvent *pEvent)
|
||||||
{
|
{
|
||||||
|
bool fromMouseInput = IsMouseInputActive();
|
||||||
if (pEvent->button() == Qt::LeftButton) mButtonsPressed &= ~eLeftButton;
|
if (pEvent->button() == Qt::LeftButton) mButtonsPressed &= ~eLeftButton;
|
||||||
if (pEvent->button() == Qt::MidButton) mButtonsPressed &= ~eMiddleButton;
|
if (pEvent->button() == Qt::MidButton) mButtonsPressed &= ~eMiddleButton;
|
||||||
if (pEvent->button() == Qt::RightButton) mButtonsPressed &= ~eRightButton;
|
if (pEvent->button() == Qt::RightButton) mButtonsPressed &= ~eRightButton;
|
||||||
|
|
||||||
// Make cursor visible and emit mouse click event if middle/right mouse buttons are both released
|
// Make cursor visible if needed
|
||||||
if (!IsMouseInputActive())
|
if (!IsMouseInputActive())
|
||||||
{
|
|
||||||
SetCursorVisible(true);
|
SetCursorVisible(true);
|
||||||
emit MouseClick(pEvent);
|
|
||||||
}
|
// Emit mouse release event if we didn't just exit mouse input (or regardless on left click)
|
||||||
|
if (!fromMouseInput || (pEvent->button() == Qt::LeftButton))
|
||||||
|
emit MouseRelease(pEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditorGLWidget::keyPressEvent(QKeyEvent *pEvent)
|
void CEditorGLWidget::keyPressEvent(QKeyEvent *pEvent)
|
||||||
|
|
|
@ -54,6 +54,7 @@ signals:
|
||||||
void Render(CCamera& Camera);
|
void Render(CCamera& Camera);
|
||||||
void PostRender();
|
void PostRender();
|
||||||
void MouseClick(QMouseEvent *pEvent);
|
void MouseClick(QMouseEvent *pEvent);
|
||||||
|
void MouseRelease(QMouseEvent *pEvent);
|
||||||
void MouseDrag(QMouseEvent *pEvent);
|
void MouseDrag(QMouseEvent *pEvent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
145
UI/CGizmo.cpp
145
UI/CGizmo.cpp
|
@ -2,6 +2,8 @@
|
||||||
#include <Common/Math.h>
|
#include <Common/Math.h>
|
||||||
#include <Core/CRenderer.h>
|
#include <Core/CRenderer.h>
|
||||||
#include <Core/CResCache.h>
|
#include <Core/CResCache.h>
|
||||||
|
#include <Core/CDrawUtil.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
CGizmo::CGizmo()
|
CGizmo::CGizmo()
|
||||||
{
|
{
|
||||||
|
@ -15,9 +17,10 @@ CGizmo::CGizmo()
|
||||||
mPosition = CVector3f::skZero;
|
mPosition = CVector3f::skZero;
|
||||||
mRotation = CQuaternion::skIdentity;
|
mRotation = CQuaternion::skIdentity;
|
||||||
mScale = CVector3f::skOne;
|
mScale = CVector3f::skOne;
|
||||||
mDeltaPosition = CVector3f::skZero;
|
mDeltaTranslation = CVector3f::skZero;
|
||||||
mDeltaRotation = CQuaternion::skIdentity;
|
mDeltaRotation = CQuaternion::skIdentity;
|
||||||
mDeltaScale = CVector3f::skOne;
|
mDeltaScale = CVector3f::skOne;
|
||||||
|
mSetOffset = false;
|
||||||
mFlipScaleX = false;
|
mFlipScaleX = false;
|
||||||
mFlipScaleY = false;
|
mFlipScaleY = false;
|
||||||
mFlipScaleZ = false;
|
mFlipScaleZ = false;
|
||||||
|
@ -109,11 +112,10 @@ void CGizmo::UpdateForCamera(const CCamera &camera)
|
||||||
mBillboardRotation = CQuaternion::FromAxisAngle(angle, axis);
|
mBillboardRotation = CQuaternion::FromAxisAngle(angle, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGizmo::IntersectsRay(const CRay &ray)
|
bool CGizmo::CheckSelectedAxes(const CRay &ray)
|
||||||
{
|
{
|
||||||
// todo: fix raycasting for rotate gizmo; currently it can hit the invisible back side of the model
|
// todo: fix raycasting for rotate gizmo; currently it can hit the invisible back side of the model
|
||||||
CRay localRay = ray.Transformed(mTransform.Inverse());
|
CRay localRay = ray.Transformed(mTransform.Inverse());
|
||||||
float threshold = 0.02f * mGizmoSize * mCameraDist;
|
|
||||||
|
|
||||||
// Do raycast on each model
|
// Do raycast on each model
|
||||||
SModelPart *pPart = mpCurrentParts;
|
SModelPart *pPart = mpCurrentParts;
|
||||||
|
@ -126,7 +128,12 @@ bool CGizmo::IntersectsRay(const CRay &ray)
|
||||||
|
|
||||||
for (u32 iPart = 0; iPart < mNumCurrentParts; iPart++)
|
for (u32 iPart = 0; iPart < mNumCurrentParts; iPart++)
|
||||||
{
|
{
|
||||||
if (!pPart->enableRayCast) continue;
|
if (!pPart->enableRayCast)
|
||||||
|
{
|
||||||
|
pPart++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
CModel *pModel = pPart->pModel;
|
CModel *pModel = pPart->pModel;
|
||||||
|
|
||||||
// Ray/Model AABox test - allow buffer room because lines are small
|
// Ray/Model AABox test - allow buffer room because lines are small
|
||||||
|
@ -141,7 +148,7 @@ bool CGizmo::IntersectsRay(const CRay &ray)
|
||||||
|
|
||||||
for (u32 iSurf = 0; iSurf < pModel->GetSurfaceCount(); iSurf++)
|
for (u32 iSurf = 0; iSurf < pModel->GetSurfaceCount(); iSurf++)
|
||||||
{
|
{
|
||||||
// Skip surface/box check
|
// Skip surface/box check - since we use lines the boxes might be too small
|
||||||
SSurface *pSurf = pModel->GetSurface(iSurf);
|
SSurface *pSurf = pModel->GetSurface(iSurf);
|
||||||
std::pair<bool,float> surfCheck = pSurf->IntersectsRay(localRay, 0.05f);
|
std::pair<bool,float> surfCheck = pSurf->IntersectsRay(localRay, 0.05f);
|
||||||
|
|
||||||
|
@ -183,11 +190,129 @@ bool CGizmo::IntersectsRay(const CRay &ray)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 CGizmo::NumSelectedAxes()
|
||||||
|
{
|
||||||
|
u32 out = 0;
|
||||||
|
|
||||||
|
for (u32 iAxis = 1; iAxis < 8; iAxis <<= 1)
|
||||||
|
if (mSelectedAxes & (EGizmoAxes) iAxis) out++;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGizmo::ResetSelectedAxes()
|
||||||
|
{
|
||||||
|
mSelectedAxes = eNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGizmo::StartTransform()
|
||||||
|
{
|
||||||
|
mSetOffset = false;
|
||||||
|
mTotalTranslation = CVector3f::skZero;
|
||||||
|
mTotalRotation = CQuaternion::skIdentity;
|
||||||
|
mTotalScale = CVector3f::skOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGizmo::TransformFromInput(const CRay& ray, const CCamera& camera)
|
||||||
|
{
|
||||||
|
if (mMode == eTranslate)
|
||||||
|
{
|
||||||
|
// Create translate plane
|
||||||
|
CVector3f axisA, axisB;
|
||||||
|
u32 numAxes = NumSelectedAxes();
|
||||||
|
|
||||||
|
if (numAxes == 1)
|
||||||
|
{
|
||||||
|
if (mSelectedAxes & eX) axisB = mRotation.XAxis();
|
||||||
|
else if (mSelectedAxes & eY) axisB = mRotation.YAxis();
|
||||||
|
else axisB = mRotation.ZAxis();
|
||||||
|
|
||||||
|
CVector3f gizmoToCamera = (mPosition - camera.Position()).Normalized();
|
||||||
|
axisA = axisB.Cross(gizmoToCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (numAxes == 2)
|
||||||
|
{
|
||||||
|
axisA = (mSelectedAxes & eX ? mRotation.XAxis() : mRotation.YAxis());
|
||||||
|
axisB = (mSelectedAxes & eZ ? mRotation.ZAxis() : mRotation.YAxis());
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector3f planeNormal = axisA.Cross(axisB);
|
||||||
|
mTranslatePlane.Redefine(planeNormal, mPosition);
|
||||||
|
|
||||||
|
// Do translate
|
||||||
|
std::pair<bool,float> result = Math::RayPlaneIntersecton(ray, mTranslatePlane);
|
||||||
|
|
||||||
|
if (result.first)
|
||||||
|
{
|
||||||
|
CVector3f hit = ray.PointOnRay(result.second);
|
||||||
|
CVector3f localDelta = mRotation.Inverse() * (hit - mPosition);
|
||||||
|
|
||||||
|
// Calculate new position
|
||||||
|
CVector3f newPos = mPosition;
|
||||||
|
if (mSelectedAxes & eX) newPos += mRotation.XAxis() * localDelta.x;
|
||||||
|
if (mSelectedAxes & eY) newPos += mRotation.YAxis() * localDelta.y;
|
||||||
|
if (mSelectedAxes & eZ) newPos += mRotation.ZAxis() * localDelta.z;
|
||||||
|
|
||||||
|
// Check relativity of new pos to camera to reduce issue where the gizmo might
|
||||||
|
// go flying off into the distance if newPosToCamera is parallel to the plane
|
||||||
|
CVector3f newPosToCamera = (newPos - camera.Position()).Normalized();
|
||||||
|
float dot = Math::Abs(planeNormal.Dot(newPosToCamera));
|
||||||
|
if (dot < 0.02f) return false;
|
||||||
|
|
||||||
|
// Set offset
|
||||||
|
if (!mSetOffset)
|
||||||
|
{
|
||||||
|
mTranslateOffset = mPosition - newPos;
|
||||||
|
mDeltaTranslation = CVector3f::skZero;
|
||||||
|
mSetOffset = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply translation
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mDeltaTranslation = mRotation.Inverse() * (newPos - mPosition + mTranslateOffset);
|
||||||
|
mTotalTranslation += mDeltaTranslation;
|
||||||
|
mPosition = newPos + mTranslateOffset;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mDeltaTranslation = CVector3f::skZero;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGizmo::EndTransform()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CGizmo::EGizmoMode CGizmo::Mode()
|
CGizmo::EGizmoMode CGizmo::Mode()
|
||||||
{
|
{
|
||||||
return mMode;
|
return mMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CVector3f CGizmo::Position()
|
||||||
|
{
|
||||||
|
return mPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector3f CGizmo::DeltaTranslation()
|
||||||
|
{
|
||||||
|
return mDeltaTranslation;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector3f CGizmo::TotalTranslation()
|
||||||
|
{
|
||||||
|
return mTotalTranslation;
|
||||||
|
}
|
||||||
|
|
||||||
void CGizmo::SetMode(EGizmoMode mode)
|
void CGizmo::SetMode(EGizmoMode mode)
|
||||||
{
|
{
|
||||||
mMode = mode;
|
mMode = mode;
|
||||||
|
@ -197,16 +322,22 @@ void CGizmo::SetMode(EGizmoMode mode)
|
||||||
case eTranslate:
|
case eTranslate:
|
||||||
mpCurrentParts = smTranslateModels;
|
mpCurrentParts = smTranslateModels;
|
||||||
mNumCurrentParts = 9;
|
mNumCurrentParts = 9;
|
||||||
|
mDeltaRotation = CQuaternion::skIdentity;
|
||||||
|
mDeltaScale = CVector3f::skOne;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eRotate:
|
case eRotate:
|
||||||
mpCurrentParts = smRotateModels;
|
mpCurrentParts = smRotateModels;
|
||||||
mNumCurrentParts = 4;
|
mNumCurrentParts = 4;
|
||||||
|
mDeltaTranslation = CVector3f::skZero;
|
||||||
|
mDeltaScale = CVector3f::skOne;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eScale:
|
case eScale:
|
||||||
mpCurrentParts = smScaleModels;
|
mpCurrentParts = smScaleModels;
|
||||||
mNumCurrentParts = 10;
|
mNumCurrentParts = 10;
|
||||||
|
mDeltaTranslation = CVector3f::skZero;
|
||||||
|
mDeltaRotation = CQuaternion::skIdentity;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,9 +347,9 @@ void CGizmo::SetPosition(const CVector3f& position)
|
||||||
mPosition = position;
|
mPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGizmo::ResetSelectedAxes()
|
void CGizmo::SetOrientation(const CQuaternion& orientation)
|
||||||
{
|
{
|
||||||
mSelectedAxes = eNone;
|
mRotation = orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PRIVATE STATIC ************
|
// ************ PRIVATE STATIC ************
|
||||||
|
|
28
UI/CGizmo.h
28
UI/CGizmo.h
|
@ -1,8 +1,9 @@
|
||||||
#ifndef CGIZMO_H
|
#ifndef CGIZMO_H
|
||||||
#define CGIZMO_H
|
#define CGIZMO_H
|
||||||
|
|
||||||
#include <Common/CVector3f.h>
|
#include <Common/CPlane.h>
|
||||||
#include <Common/CQuaternion.h>
|
#include <Common/CQuaternion.h>
|
||||||
|
#include <Common/CVector3f.h>
|
||||||
#include <Common/EnumUtil.h>
|
#include <Common/EnumUtil.h>
|
||||||
#include <Core/CCamera.h>
|
#include <Core/CCamera.h>
|
||||||
#include <Core/CToken.h>
|
#include <Core/CToken.h>
|
||||||
|
@ -63,15 +64,24 @@ private:
|
||||||
|
|
||||||
CTransform4f mTransform;
|
CTransform4f mTransform;
|
||||||
CVector3f mPosition;
|
CVector3f mPosition;
|
||||||
|
CVector3f mDeltaTranslation;
|
||||||
|
CVector3f mTotalTranslation;
|
||||||
CQuaternion mRotation;
|
CQuaternion mRotation;
|
||||||
CVector3f mScale;
|
|
||||||
CVector3f mDeltaPosition;
|
|
||||||
CQuaternion mDeltaRotation;
|
CQuaternion mDeltaRotation;
|
||||||
|
CQuaternion mTotalRotation;
|
||||||
|
CVector3f mScale;
|
||||||
CVector3f mDeltaScale;
|
CVector3f mDeltaScale;
|
||||||
|
CVector3f mTotalScale;
|
||||||
bool mFlipScaleX;
|
bool mFlipScaleX;
|
||||||
bool mFlipScaleY;
|
bool mFlipScaleY;
|
||||||
bool mFlipScaleZ;
|
bool mFlipScaleZ;
|
||||||
|
|
||||||
|
CPlane mTranslatePlane;
|
||||||
|
CVector3f mLastTranslatePosition;
|
||||||
|
CVector3f mTranslateOffset;
|
||||||
|
bool mSetOffset;
|
||||||
|
|
||||||
|
|
||||||
struct SModelPart
|
struct SModelPart
|
||||||
{
|
{
|
||||||
EGizmoAxes modelAxes;
|
EGizmoAxes modelAxes;
|
||||||
|
@ -104,12 +114,20 @@ public:
|
||||||
void IncrementSize();
|
void IncrementSize();
|
||||||
void DecrementSize();
|
void DecrementSize();
|
||||||
void UpdateForCamera(const CCamera& camera);
|
void UpdateForCamera(const CCamera& camera);
|
||||||
bool IntersectsRay(const CRay& ray);
|
bool CheckSelectedAxes(const CRay& ray);
|
||||||
|
u32 NumSelectedAxes();
|
||||||
|
void ResetSelectedAxes();
|
||||||
|
void StartTransform();
|
||||||
|
bool TransformFromInput(const CRay& ray, const CCamera& camera);
|
||||||
|
void EndTransform();
|
||||||
|
|
||||||
EGizmoMode Mode();
|
EGizmoMode Mode();
|
||||||
|
CVector3f Position();
|
||||||
|
CVector3f DeltaTranslation();
|
||||||
|
CVector3f TotalTranslation();
|
||||||
void SetMode(EGizmoMode mode);
|
void SetMode(EGizmoMode mode);
|
||||||
void SetPosition(const CVector3f& position);
|
void SetPosition(const CVector3f& position);
|
||||||
void ResetSelectedAxes();
|
void SetOrientation(const CQuaternion& orientation);
|
||||||
|
|
||||||
// Protected
|
// Protected
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
|
#include <QComboBox>
|
||||||
#include <Core/Log.h>
|
#include <Core/Log.h>
|
||||||
#include "WDraggableSpinBox.h"
|
#include "WDraggableSpinBox.h"
|
||||||
|
|
||||||
|
@ -32,6 +33,9 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
||||||
mpHoverNode = nullptr;
|
mpHoverNode = nullptr;
|
||||||
mDrawSky = true;
|
mDrawSky = true;
|
||||||
mShowGizmo = false;
|
mShowGizmo = false;
|
||||||
|
mGizmoHovering = false;
|
||||||
|
mGizmoTransforming = false;
|
||||||
|
mUpdateUILater = false;
|
||||||
|
|
||||||
mFrameCount = 0;
|
mFrameCount = 0;
|
||||||
mFPSTimer.Start();
|
mFPSTimer.Start();
|
||||||
|
@ -47,7 +51,6 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
||||||
|
|
||||||
delete pOldTitleBar;
|
delete pOldTitleBar;
|
||||||
|
|
||||||
|
|
||||||
// Initialize UI stuff
|
// Initialize UI stuff
|
||||||
ui->ModifyTabContents->SetEditor(this);
|
ui->ModifyTabContents->SetEditor(this);
|
||||||
ui->InstancesTabContents->SetEditor(this, mpSceneManager);
|
ui->InstancesTabContents->SetEditor(this, mpSceneManager);
|
||||||
|
@ -55,17 +58,27 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
||||||
ui->CamSpeedSpinBox->SetDefaultValue(1.0);
|
ui->CamSpeedSpinBox->SetDefaultValue(1.0);
|
||||||
ResetHover();
|
ResetHover();
|
||||||
|
|
||||||
|
mTransformSpace = eWorldTransform;
|
||||||
|
|
||||||
|
QComboBox *pTransformCombo = new QComboBox(this);
|
||||||
|
pTransformCombo->setMinimumWidth(75);
|
||||||
|
pTransformCombo->addItem("World");
|
||||||
|
pTransformCombo->addItem("Local");
|
||||||
|
ui->MainToolBar->insertWidget(0, pTransformCombo);
|
||||||
|
|
||||||
// Initialize offscreen actions
|
// Initialize offscreen actions
|
||||||
addAction(ui->ActionIncrementGizmo);
|
addAction(ui->ActionIncrementGizmo);
|
||||||
addAction(ui->ActionDecrementGizmo);
|
addAction(ui->ActionDecrementGizmo);
|
||||||
|
|
||||||
// Connect signals and slots
|
// Connect signals and slots
|
||||||
|
connect(pTransformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(SetTransformSpace(int)));
|
||||||
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
|
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
|
||||||
connect(ui->MainViewport, SIGNAL(PreRender()), this, SLOT(ViewportPreRender()));
|
connect(ui->MainViewport, SIGNAL(PreRender()), this, SLOT(ViewportPreRender()));
|
||||||
connect(ui->MainViewport, SIGNAL(Render(CCamera&)), this, SLOT(ViewportRender(CCamera&)));
|
connect(ui->MainViewport, SIGNAL(Render(CCamera&)), this, SLOT(ViewportRender(CCamera&)));
|
||||||
connect(ui->MainViewport, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
|
connect(ui->MainViewport, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
|
||||||
connect(ui->MainViewport, SIGNAL(frameSwapped()), this, SLOT(ViewportPostRender()));
|
connect(ui->MainViewport, SIGNAL(frameSwapped()), this, SLOT(ViewportPostRender()));
|
||||||
connect(ui->MainViewport, SIGNAL(MouseClick(QMouseEvent*)), this, SLOT(ViewportMouseClick(QMouseEvent*)));
|
connect(ui->MainViewport, SIGNAL(MouseClick(QMouseEvent*)), this, SLOT(ViewportMouseClick(QMouseEvent*)));
|
||||||
|
connect(ui->MainViewport, SIGNAL(MouseRelease(QMouseEvent*)), this, SLOT(ViewportMouseRelease(QMouseEvent*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CWorldEditor::~CWorldEditor()
|
CWorldEditor::~CWorldEditor()
|
||||||
|
@ -135,8 +148,16 @@ void CWorldEditor::ViewportRayCast(CRay Ray)
|
||||||
{
|
{
|
||||||
if (!ui->MainViewport->IsMouseInputActive())
|
if (!ui->MainViewport->IsMouseInputActive())
|
||||||
{
|
{
|
||||||
// Gizmo ray check
|
if (!mGizmoTransforming)
|
||||||
mGizmoHovering = mGizmo.IntersectsRay(Ray);
|
{
|
||||||
|
// Gizmo hover check
|
||||||
|
if (mShowGizmo && !mSelectedNodes.empty())
|
||||||
|
mGizmoHovering = mGizmo.CheckSelectedAxes(Ray);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mGizmoHovering = false;
|
||||||
|
mGizmo.ResetSelectedAxes();
|
||||||
|
}
|
||||||
|
|
||||||
// Scene ray check
|
// Scene ray check
|
||||||
SRayIntersection Result = mpSceneManager->SceneRayCast(Ray);
|
SRayIntersection Result = mpSceneManager->SceneRayCast(Ray);
|
||||||
|
@ -156,7 +177,29 @@ void CWorldEditor::ViewportRayCast(CRay Ray)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool moved = mGizmo.TransformFromInput(Ray, ui->MainViewport->Camera());
|
||||||
|
|
||||||
|
if (moved)
|
||||||
|
{
|
||||||
|
CVector3f delta = mGizmo.DeltaTranslation();
|
||||||
|
|
||||||
|
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
||||||
|
{
|
||||||
|
(*it)->Translate(delta, mTransformSpace);
|
||||||
|
(*it)->BuildLightList(this->mpArea);
|
||||||
|
}
|
||||||
|
RecalculateSelectionBounds();
|
||||||
|
mUpdateUILater = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!mGizmoTransforming)
|
||||||
|
{
|
||||||
|
mGizmoHovering = false;
|
||||||
mGizmo.ResetSelectedAxes();
|
mGizmo.ResetSelectedAxes();
|
||||||
|
}
|
||||||
ResetHover();
|
ResetHover();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,13 +272,32 @@ void CWorldEditor::ClearSelection()
|
||||||
// ************ SLOTS ************
|
// ************ SLOTS ************
|
||||||
void CWorldEditor::ViewportMouseDrag(QMouseEvent *pEvent)
|
void CWorldEditor::ViewportMouseDrag(QMouseEvent *pEvent)
|
||||||
{
|
{
|
||||||
// todo: gizmo translate/rotate/scale implementation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::ViewportMouseClick(QMouseEvent *pEvent)
|
void CWorldEditor::ViewportMouseClick(QMouseEvent *pEvent)
|
||||||
{
|
{
|
||||||
// Process left click (button press)
|
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
||||||
|
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
||||||
|
|
||||||
|
if (mGizmoHovering && !AltPressed && !CtrlPressed)
|
||||||
|
{
|
||||||
|
mGizmoTransforming = true;
|
||||||
|
mGizmo.StartTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorldEditor::ViewportMouseRelease(QMouseEvent *pEvent)
|
||||||
|
{
|
||||||
if (pEvent->button() == Qt::LeftButton)
|
if (pEvent->button() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
// Gizmo transform stop
|
||||||
|
if (mGizmoTransforming)
|
||||||
|
{
|
||||||
|
mGizmoTransforming = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object selection/deselection
|
||||||
|
else if (!ui->MainViewport->IsMouseInputActive())
|
||||||
{
|
{
|
||||||
bool ValidNode = ((mpHoverNode) && (mpHoverNode->NodeType() != eStaticNode));
|
bool ValidNode = ((mpHoverNode) && (mpHoverNode->NodeType() != eStaticNode));
|
||||||
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
||||||
|
@ -251,22 +313,32 @@ void CWorldEditor::ViewportMouseClick(QMouseEvent *pEvent)
|
||||||
DeselectNode(mpHoverNode);
|
DeselectNode(mpHoverNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other - select object
|
// Ctrl pressed - add object to selection
|
||||||
else
|
else if (CtrlPressed)
|
||||||
{
|
{
|
||||||
// Control not pressed - clear existing selection
|
|
||||||
if (!CtrlPressed)
|
|
||||||
ClearSelection();
|
|
||||||
|
|
||||||
// Add hover node to selection
|
// Add hover node to selection
|
||||||
if (ValidNode)
|
if (ValidNode)
|
||||||
SelectNode(mpHoverNode);
|
SelectNode(mpHoverNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateSelectionUI();
|
// Neither pressed
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the gizmo isn't under the mouse, clear existing selection + select object (if applicable)
|
||||||
|
if (!mGizmoHovering)
|
||||||
|
{
|
||||||
|
ClearSelection();
|
||||||
|
|
||||||
|
if (ValidNode)
|
||||||
|
SelectNode(mpHoverNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Later, possibly expand to context menu creation for right-click
|
UpdateSelectionUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: context menu creation on right-click goes here
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ SLOTS ************
|
// ************ SLOTS ************
|
||||||
|
@ -298,8 +370,10 @@ void CWorldEditor::ViewportRender(CCamera& Camera)
|
||||||
|
|
||||||
if (mShowGizmo && (mSelectedNodes.size() > 0))
|
if (mShowGizmo && (mSelectedNodes.size() > 0))
|
||||||
{
|
{
|
||||||
|
mpRenderer->ClearDepthBuffer();
|
||||||
|
|
||||||
Camera.LoadMatrices();
|
Camera.LoadMatrices();
|
||||||
mGizmo.UpdateForCamera(Camera);
|
if (!mGizmoTransforming) mGizmo.UpdateForCamera(Camera);
|
||||||
mGizmo.AddToRenderer(mpRenderer);
|
mGizmo.AddToRenderer(mpRenderer);
|
||||||
|
|
||||||
if (mGizmo.Mode() == CGizmo::eRotate)
|
if (mGizmo.Mode() == CGizmo::eRotate)
|
||||||
|
@ -318,6 +392,12 @@ void CWorldEditor::ViewportPostRender()
|
||||||
// Update UI with raycast results
|
// Update UI with raycast results
|
||||||
UpdateCursor();
|
UpdateCursor();
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
|
|
||||||
|
if (mUpdateUILater)
|
||||||
|
{
|
||||||
|
UpdateSelectionUI();
|
||||||
|
mUpdateUILater = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::SetViewportSize(int Width, int Height)
|
void CWorldEditor::SetViewportSize(int Width, int Height)
|
||||||
|
@ -325,6 +405,22 @@ void CWorldEditor::SetViewportSize(int Width, int Height)
|
||||||
mpRenderer->SetViewportSize(Width, Height);
|
mpRenderer->SetViewportSize(Width, Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWorldEditor::SetTransformSpace(int space)
|
||||||
|
{
|
||||||
|
switch (space)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
mTransformSpace = eWorldTransform;
|
||||||
|
mGizmo.SetOrientation(CQuaternion::skIdentity);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
mTransformSpace = eLocalTransform;
|
||||||
|
if (!mSelectedNodes.empty())
|
||||||
|
mGizmo.SetOrientation(mSelectedNodes.front()->AbsoluteRotation());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ************ PRIVATE ************
|
// ************ PRIVATE ************
|
||||||
void CWorldEditor::RecalculateSelectionBounds()
|
void CWorldEditor::RecalculateSelectionBounds()
|
||||||
{
|
{
|
||||||
|
@ -396,13 +492,21 @@ void CWorldEditor::UpdateSelectionUI()
|
||||||
ui->SelectionInfoLabel->setText(SelectionText);
|
ui->SelectionInfoLabel->setText(SelectionText);
|
||||||
|
|
||||||
// Update transform
|
// Update transform
|
||||||
CVector3f pos = (!mSelectedNodes.empty() ? mSelectedNodes.front()->GetAbsolutePosition() : CVector3f::skZero);
|
CVector3f pos = (!mSelectedNodes.empty() ? mSelectedNodes.front()->AbsolutePosition() : CVector3f::skZero);
|
||||||
ui->XSpinBox->setValue(pos.x);
|
ui->XSpinBox->setValue(pos.x);
|
||||||
ui->YSpinBox->setValue(pos.y);
|
ui->YSpinBox->setValue(pos.y);
|
||||||
ui->ZSpinBox->setValue(pos.z);
|
ui->ZSpinBox->setValue(pos.z);
|
||||||
|
|
||||||
// Update gizmo
|
// Update gizmo
|
||||||
|
if (!mGizmoTransforming)
|
||||||
|
{
|
||||||
mGizmo.SetPosition(pos);
|
mGizmo.SetPosition(pos);
|
||||||
|
|
||||||
|
if ((mTransformSpace == eLocalTransform) && !mSelectedNodes.empty())
|
||||||
|
mGizmo.SetOrientation(mSelectedNodes.front()->AbsoluteRotation());
|
||||||
|
else
|
||||||
|
mGizmo.SetOrientation(CQuaternion::skIdentity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ ACTIONS ************
|
// ************ ACTIONS ************
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <Common/CTimer.h>
|
#include <Common/CTimer.h>
|
||||||
#include <Common/EKeyInputs.h>
|
#include <Common/EKeyInputs.h>
|
||||||
#include <Common/SRayIntersection.h>
|
#include <Common/SRayIntersection.h>
|
||||||
|
#include <Common/ETransformSpace.h>
|
||||||
#include <Core/CRenderer.h>
|
#include <Core/CRenderer.h>
|
||||||
#include <Core/CSceneManager.h>
|
#include <Core/CSceneManager.h>
|
||||||
#include <Core/CToken.h>
|
#include <Core/CToken.h>
|
||||||
|
@ -25,6 +26,7 @@ class CWorldEditor : public QMainWindow
|
||||||
CRenderer *mpRenderer;
|
CRenderer *mpRenderer;
|
||||||
CSceneManager *mpSceneManager;
|
CSceneManager *mpSceneManager;
|
||||||
CGizmo mGizmo;
|
CGizmo mGizmo;
|
||||||
|
ETransformSpace mTransformSpace;
|
||||||
CCamera mCamera;
|
CCamera mCamera;
|
||||||
CGameArea *mpArea;
|
CGameArea *mpArea;
|
||||||
CWorld *mpWorld;
|
CWorld *mpWorld;
|
||||||
|
@ -34,6 +36,8 @@ class CWorldEditor : public QMainWindow
|
||||||
bool mDrawSky;
|
bool mDrawSky;
|
||||||
bool mShowGizmo;
|
bool mShowGizmo;
|
||||||
bool mGizmoHovering;
|
bool mGizmoHovering;
|
||||||
|
bool mGizmoTransforming;
|
||||||
|
bool mUpdateUILater;
|
||||||
|
|
||||||
CVector3f mHoverPoint;
|
CVector3f mHoverPoint;
|
||||||
CSceneNode *mpHoverNode;
|
CSceneNode *mpHoverNode;
|
||||||
|
@ -64,7 +68,9 @@ public slots:
|
||||||
void ViewportPostRender();
|
void ViewportPostRender();
|
||||||
void ViewportMouseDrag(QMouseEvent *pEvent);
|
void ViewportMouseDrag(QMouseEvent *pEvent);
|
||||||
void ViewportMouseClick(QMouseEvent *pEvent);
|
void ViewportMouseClick(QMouseEvent *pEvent);
|
||||||
|
void ViewportMouseRelease(QMouseEvent *pEvent);
|
||||||
void SetViewportSize(int Width, int Height);
|
void SetViewportSize(int Width, int Height);
|
||||||
|
void SetTransformSpace(int space);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::CWorldEditor *ui;
|
Ui::CWorldEditor *ui;
|
||||||
|
|
|
@ -440,13 +440,16 @@
|
||||||
<addaction name="menuWindow"/>
|
<addaction name="menuWindow"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
<widget class="QToolBar" name="Toolbar">
|
<widget class="QToolBar" name="FileToolBar">
|
||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
<enum>Qt::NoContextMenu</enum>
|
<enum>Qt::NoContextMenu</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>toolBar_2</string>
|
<string>toolBar_2</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="movable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<attribute name="toolBarArea">
|
<attribute name="toolBarArea">
|
||||||
<enum>TopToolBarArea</enum>
|
<enum>TopToolBarArea</enum>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
@ -593,13 +596,19 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QToolBar" name="toolBar">
|
<widget class="QToolBar" name="MainToolBar">
|
||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
<enum>Qt::NoContextMenu</enum>
|
<enum>Qt::NoContextMenu</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>toolBar</string>
|
<string>toolBar</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<attribute name="toolBarArea">
|
<attribute name="toolBarArea">
|
||||||
<enum>TopToolBarArea</enum>
|
<enum>TopToolBarArea</enum>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
|
Loading…
Reference in New Issue