diff --git a/renderdoc/api/replay/control_types.h b/renderdoc/api/replay/control_types.h index 2836ee2c0..bafb15599 100644 --- a/renderdoc/api/replay/control_types.h +++ b/renderdoc/api/replay/control_types.h @@ -54,13 +54,13 @@ struct MeshFormat float farPlane; }; +class Camera; + struct MeshDisplay { MeshDataStage type; - bool32 arcballCamera; - FloatVector cameraPos; - FloatVector cameraRot; + Camera *cam; bool32 ortho; float fov, aspect; diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 3398765df..68080565e 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -208,6 +208,30 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC RemoteRenderer_RemoteSupportedRepla extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC RemoteRenderer_CreateProxyRenderer(RemoteRenderer *remote, uint32_t proxyid, const char *logfile, float *progress, ReplayRenderer **rend); +////////////////////////////////////////////////////////////////////////// +// camera +////////////////////////////////////////////////////////////////////////// + +#ifdef RENDERDOC_EXPORTS +class Camera; +#else +class Camera { }; +#endif + +extern "C" RENDERDOC_API Camera *RENDERDOC_CC Camera_InitArcball(); +extern "C" RENDERDOC_API Camera *RENDERDOC_CC Camera_InitFPSLook(); +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_Shutdown(Camera *c); + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_SetPosition(Camera *c, float x, float y, float z); + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_SetFPSRotation(Camera *c, float x, float y, float z); + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_SetArcballDistance(Camera *c, float dist); +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_ResetArcball(Camera *c); +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_RotateArcball(Camera *c, float ax, float ay, float bx, float by); + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_GetBasis(Camera *c, FloatVector *pos, FloatVector *fwd, FloatVector *right, FloatVector *up); + ////////////////////////////////////////////////////////////////////////// // Maths/format related exports ////////////////////////////////////////////////////////////////////////// @@ -215,9 +239,6 @@ extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC RemoteRenderer_CreatePr extern "C" RENDERDOC_API float RENDERDOC_CC Maths_HalfToFloat(uint16_t half); extern "C" RENDERDOC_API uint16_t RENDERDOC_CC Maths_FloatToHalf(float f); -extern "C" RENDERDOC_API void RENDERDOC_CC Maths_CameraArcball(const FloatVector &lookat, float dist, const FloatVector &rot, FloatVector *pos, FloatVector *fwd, FloatVector *right, FloatVector *up); -extern "C" RENDERDOC_API void RENDERDOC_CC Maths_CameraFPSLook(const FloatVector &lookpos, const FloatVector &rot, FloatVector *pos, FloatVector *fwd, FloatVector *right, FloatVector *up); - ////////////////////////////////////////////////////////////////////////// // Create a replay renderer, for playback and analysis. // diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index d8ca7ea27..9cf8040a1 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -1815,13 +1815,7 @@ uint32_t D3D11DebugManager::PickVertex(uint32_t frameID, uint32_t eventID, MeshD Matrix4f projMat = Matrix4f::Perspective(90.0f, 0.1f, 100000.0f, float(GetWidth())/float(GetHeight())); - Camera cam; - if(cfg.arcballCamera) - cam.Arcball(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), cfg.cameraPos.w, Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z)); - else - cam.fpsLook(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z)); - - Matrix4f camMat = cam.GetMatrix(); + Matrix4f camMat = cfg.cam ? cfg.cam->GetMatrix() : Matrix4f::Identity(); cbuf.PickMVP = projMat.Mul(camMat); ResourceFormat resFmt; diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index 02f695917..937e7396f 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -4589,13 +4589,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec Matrix4f projMat = Matrix4f::Perspective(90.0f, 0.1f, 100000.0f, float(GetWidth())/float(GetHeight())); - Camera cam; - if(cfg.arcballCamera) - cam.Arcball(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), cfg.cameraPos.w, Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z)); - else - cam.fpsLook(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z)); - - Matrix4f camMat = cam.GetMatrix(); + Matrix4f camMat = cfg.cam ? cfg.cam->GetMatrix() : Matrix4f::Identity(); Matrix4f guessProjInv; vertexData.ModelViewProj = projMat.Mul(camMat); diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 8d9ed28eb..694a26c4c 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -1012,13 +1012,7 @@ uint32_t GLReplay::PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cf Matrix4f projMat = Matrix4f::Perspective(90.0f, 0.1f, 100000.0f, DebugData.outWidth/DebugData.outHeight); - Camera cam; - if(cfg.arcballCamera) - cam.Arcball(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), cfg.cameraPos.w, Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z)); - else - cam.fpsLook(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z)); - - Matrix4f camMat = cam.GetMatrix(); + Matrix4f camMat = cfg.cam ? cfg.cam->GetMatrix() : Matrix4f::Identity(); Matrix4f PickMVP = projMat.Mul(camMat); ResourceFormat resFmt; @@ -3337,13 +3331,7 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vectorGetMatrix() : Matrix4f::Identity(); Matrix4f ModelViewProj = projMat.Mul(camMat); Matrix4f guessProjInv; diff --git a/renderdoc/maths/camera.cpp b/renderdoc/maths/camera.cpp index fc35babc1..c43a22db3 100644 --- a/renderdoc/maths/camera.cpp +++ b/renderdoc/maths/camera.cpp @@ -26,65 +26,104 @@ #include #include +#include "common/common.h" #include "camera.h" #include "matrix.h" -void Camera::Arcball(const Vec3f &p, float d, const Vec3f &rot) +void Camera::ResetArcball() { - pos = p; - dist = d; + dirty = true; - type = eType_Arcball; - - angles.x = rot.x; - angles.y = rot.y; + arcrot = Quatf::AxisAngle(Vec3f(1, 0, 0), 0.0f); } -void Camera::fpsLook(const Vec3f &p, const Vec3f &rot) +// https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball +void Camera::RotateArcball(const Vec2f &from, const Vec2f &to) { - pos = -p; + Vec3f a, b; + + float az = from.x * from.x + from.y * from.y; + float bz = to.x * to.x + to.y * to.y; + + // keep the controls stable by rejecting very small movements. + if(fabsf(az - bz) < 1e-5f) + return; + + if(az < 1.0f) + { + a = Vec3f(from.x, from.y, sqrt(1.0f - az)); + } + else + { + a = Vec3f(from.x, from.y, 0.0f); + a.Normalise(); + } + + if(bz < 1.0f) + { + b = Vec3f(to.x, to.y, sqrt(1.0f - bz)); + } + else + { + b = Vec3f(to.x, to.y, 0.0f); + b.Normalise(); + } + + float angle = acosf(RDCMIN(1.0f, a.Dot(b))); + + Vec3f axis = a.Cross(b); + axis.Normalise(); - angles.x = -rot.x; - angles.y = -rot.y; + dirty = true; - type = eType_FPSLook; + Quatf delta = Quatf::AxisAngle(axis, angle); + arcrot = arcrot * delta; } -const Matrix4f Camera::GetMatrix() const +void Camera::Update() { + if(!dirty) return; + if(type == eType_FPSLook) { - Matrix4f p = Matrix4f::Translation(pos); - Matrix4f r = Matrix4f::RotationXYZ(angles); + Matrix4f p = Matrix4f::Translation(-pos); + Matrix4f r = Matrix4f::RotationXYZ(-angles); - return r.Mul(p); + mat = r.Mul(p); + basis = mat.Transpose(); } else { Matrix4f p = Matrix4f::Translation(-pos); - Matrix4f r = Matrix4f::RotationXYZ(angles); + Matrix4f r = arcrot.GetMatrix(); Matrix4f d = Matrix4f::Translation(Vec3f(0.0f, 0.0f, dist)); - return d.Mul(r.Mul(p)); + mat = d.Mul(r.Mul(p)); } } -const Vec3f Camera::GetPosition() const +const Matrix4f Camera::GetMatrix() { - return GetMatrix().GetPosition(); + Update(); + return mat; } -const Vec3f Camera::GetForward() const +const Vec3f Camera::GetPosition() { - return Matrix4f::RotationZYX(-angles).GetForward(); + return pos; } -const Vec3f Camera::GetRight() const +const Vec3f Camera::GetForward() { - return Matrix4f::RotationZYX(-angles).GetRight(); + return basis.GetForward(); } -const Vec3f Camera::GetUp() const +const Vec3f Camera::GetRight() { - return Matrix4f::RotationZYX(-angles).GetUp(); + return basis.GetRight(); +} + +const Vec3f Camera::GetUp() +{ + return basis.GetUp(); } diff --git a/renderdoc/maths/camera.h b/renderdoc/maths/camera.h index 031937526..283ee4521 100644 --- a/renderdoc/maths/camera.h +++ b/renderdoc/maths/camera.h @@ -26,36 +26,55 @@ #pragma once #include "vec.h" +#include "quat.h" class Matrix4f; class Camera { public: - Camera() - : type(eType_FPSLook), pos(), dist(0.0f), angles() - { } - - void Arcball(const Vec3f &pos, float dist, const Vec3f &rot); - void fpsLook(const Vec3f &pos, const Vec3f &rot); - - void SetPosition(const Vec3f &p) { pos = p; } - void SetAngles(const Vec3f &r) { angles = r; } - - const Vec3f GetPosition() const; - const Vec3f GetForward() const; - const Vec3f GetRight() const; - const Vec3f GetUp() const; - const Matrix4f GetMatrix() const; - - private: enum CameraType { eType_Arcball = 0, eType_FPSLook, - } type; + }; + + Camera(CameraType t) + : type(t), dirty(true), pos(), dist(0.0f), angles() + { + ResetArcball(); + } + + void SetPosition(const Vec3f &p) { dirty = true; pos = p; } + + // Arcball functions + void ResetArcball(); + void SetArcballDistance(float d) { dirty = true; dist = d; } + void RotateArcball(const Vec2f &from, const Vec2f &to); + + // FPS look functions + void SetFPSRotation(const Vec3f &rot) { dirty = true; angles = rot; } + + const Vec3f GetPosition(); + const Vec3f GetForward(); + const Vec3f GetRight(); + const Vec3f GetUp(); + const Matrix4f GetMatrix(); + + private: + void Update(); + + CameraType type; + + bool dirty; + Matrix4f mat, basis; Vec3f pos; + + // Arcball + Quatf arcrot; float dist; + + // FPS look Vec3f angles; }; diff --git a/renderdoc/maths/matrix.cpp b/renderdoc/maths/matrix.cpp index 342498617..7acab4a35 100644 --- a/renderdoc/maths/matrix.cpp +++ b/renderdoc/maths/matrix.cpp @@ -184,6 +184,16 @@ Matrix4f Matrix4f::Mul(const Matrix4f &o) const return m; } +Matrix4f Matrix4f::Transpose() const +{ + Matrix4f m; + for(size_t x=0; x < 4; x++) + for(size_t y=0; y < 4; y++) + m[matIdx(x,y)] = (*this)[matIdx(y,x)]; + + return m; +} + Matrix4f Matrix4f::Inverse() const { float a0 = (*this)[ 0]*(*this)[ 5] - (*this)[ 1]*(*this)[ 4]; diff --git a/renderdoc/maths/matrix.h b/renderdoc/maths/matrix.h index bb9015750..c9e348597 100644 --- a/renderdoc/maths/matrix.h +++ b/renderdoc/maths/matrix.h @@ -70,7 +70,8 @@ class Matrix4f { return f[i]; } - + + Matrix4f Transpose() const; Matrix4f Inverse() const; Matrix4f Mul(const Matrix4f &o) const; diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index e32f8c0b9..f613563a8 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -41,42 +41,52 @@ extern "C" RENDERDOC_API uint16_t RENDERDOC_CC Maths_FloatToHalf(float f) return ConvertToHalf(f); } -extern "C" RENDERDOC_API void RENDERDOC_CC Maths_CameraArcball(const FloatVector &lookat, float dist, const FloatVector &rot, FloatVector *pos, FloatVector *fwd, FloatVector *right, FloatVector *up) +extern "C" RENDERDOC_API Camera *RENDERDOC_CC Camera_InitArcball() { - Camera c; - c.Arcball(Vec3f(lookat.x, lookat.y, lookat.z), dist, Vec3f(rot.x, rot.y, rot.z)); - - Vec3f p = c.GetPosition(); - Vec3f f = c.GetForward(); - Vec3f r = c.GetRight(); - Vec3f u = c.GetUp(); - - pos->x = p.x; - pos->y = p.y; - pos->z = p.z; - - fwd->x = f.x; - fwd->y = f.y; - fwd->z = f.z; - - right->x = r.x; - right->y = r.y; - right->z = r.z; - - up->x = u.x; - up->y = u.y; - up->z = u.z; + return new Camera(Camera::eType_Arcball); } -extern "C" RENDERDOC_API void RENDERDOC_CC Maths_CameraFPSLook(const FloatVector &lookpos, const FloatVector &rot, FloatVector *pos, FloatVector *fwd, FloatVector *right, FloatVector *up) +extern "C" RENDERDOC_API Camera *RENDERDOC_CC Camera_InitFPSLook() { - Camera c; - c.fpsLook(Vec3f(lookpos.x, lookpos.y, lookpos.z), Vec3f(rot.x, rot.y, rot.z)); - - Vec3f p = c.GetPosition(); - Vec3f f = c.GetForward(); - Vec3f r = c.GetRight(); - Vec3f u = c.GetUp(); + return new Camera(Camera::eType_FPSLook); +} + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_Shutdown(Camera *c) +{ + delete c; +} + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_SetPosition(Camera *c, float x, float y, float z) +{ + c->SetPosition(Vec3f(x, y, z)); +} + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_SetFPSRotation(Camera *c, float x, float y, float z) +{ + c->SetFPSRotation(Vec3f(x, y, z)); +} + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_SetArcballDistance(Camera *c, float dist) +{ + c->SetArcballDistance(dist); +} + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_ResetArcball(Camera *c) +{ + c->ResetArcball(); +} + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_RotateArcball(Camera *c, float ax, float ay, float bx, float by) +{ + c->RotateArcball(Vec2f(ax, ay), Vec2f(bx, by)); +} + +extern "C" RENDERDOC_API void RENDERDOC_CC Camera_GetBasis(Camera *c, FloatVector *pos, FloatVector *fwd, FloatVector *right, FloatVector *up) +{ + Vec3f p = c->GetPosition(); + Vec3f f = c->GetForward(); + Vec3f r = c->GetRight(); + Vec3f u = c->GetUp(); pos->x = p.x; pos->y = p.y; diff --git a/renderdocui/Code/Cameras.cs b/renderdocui/Code/Cameras.cs index bd4c3bbc1..7546f6559 100644 --- a/renderdocui/Code/Cameras.cs +++ b/renderdocui/Code/Cameras.cs @@ -74,21 +74,16 @@ namespace renderdocui.Code abstract class CameraControls { - protected CameraControls(Camera c) + protected CameraControls() { - m_Camera = c; } + abstract public bool Update(); + + abstract public Camera Camera { get; } + abstract public void MouseWheel(object sender, MouseEventArgs e); - abstract public void Reset(Vec3f pos); - abstract public void Update(); - abstract public void Apply(); - - abstract public bool Dirty { get; } - abstract public Vec3f Position { get; } - abstract public Vec3f Rotation { get; } - virtual public void MouseClick(object sender, MouseEventArgs e) { m_DragStartPos = e.Location; @@ -157,35 +152,38 @@ namespace renderdocui.Code private Point m_DragStartPos = new Point(-1, -1); protected Point DragStartPos { get { return m_DragStartPos; } } - - protected Camera m_Camera; } class ArcballCamera : CameraControls { - public ArcballCamera(Camera c) - : base(c) + private Camera m_Camera = null; + + public override Camera Camera { get { return m_Camera; } } + + public ArcballCamera() { + m_Camera = Camera.InitArcball(); } - public override void Reset(Vec3f dist) + public void Reset(Vec3f pos, float dist) { - m_Distance = Math.Abs(dist.z); - m_Rotation = new Vec3f(); + m_LookAt = pos; + m_Distance = Math.Abs(dist); + + m_Camera.ResetArcball(); + m_Camera.SetPosition(m_LookAt); + m_Camera.SetArcballDistance(m_Distance); } public void SetDistance(float dist) { m_Distance = Math.Abs(dist); + m_Camera.SetArcballDistance(m_Distance); } - public override void Update() + public override bool Update() { - } - - public override void Apply() - { - m_Camera.Arcball(LookAtPos, m_Distance, Rotation); + return false; } public override void MouseWheel(object sender, MouseEventArgs e) @@ -194,9 +192,9 @@ namespace renderdocui.Code m_Distance = Math.Max(1e-6f, m_Distance * mod); - ((HandledMouseEventArgs)e).Handled = true; + m_Camera.SetArcballDistance(m_Distance); - m_Dirty = true; + ((HandledMouseEventArgs)e).Handled = true; } public override void MouseMove(object sender, MouseEventArgs e) @@ -213,102 +211,100 @@ namespace renderdocui.Code xdelta *= Math.Max(1.0f, m_Distance); ydelta *= Math.Max(1.0f, m_Distance); - LookAtPos.x -= m_Camera.Right.x * xdelta; - LookAtPos.y -= m_Camera.Right.y * xdelta; - LookAtPos.z -= m_Camera.Right.z * xdelta; + Vec3f pos, fwd, right, up; + m_Camera.GetBasis(out pos, out fwd, out right, out up); - LookAtPos.x += m_Camera.Up.x * ydelta; - LookAtPos.y += m_Camera.Up.y * ydelta; - LookAtPos.z += m_Camera.Up.z * ydelta; + m_LookAt.x -= right.x * xdelta; + m_LookAt.y -= right.y * xdelta; + m_LookAt.z -= right.z * xdelta; - m_Dirty = true; + m_LookAt.x += up.x * ydelta; + m_LookAt.y += up.y * ydelta; + m_LookAt.z += up.z * ydelta; + + m_Camera.SetPosition(m_LookAt); } else if (e.Button == MouseButtons.Left) { - m_Rotation.y += (float)(e.X - DragStartPos.X) / 300.0f; - m_Rotation.x += (float)(e.Y - DragStartPos.Y) / 300.0f; - - m_Dirty = true; + Control c = sender as Control; + if (c != null) + m_Camera.RotateArcball(DragStartPos, e.Location, c.ClientRectangle.Size); } } base.MouseMove(sender, e); } - bool m_Dirty = false; - public override bool Dirty - { - get - { - bool ret = m_Dirty; - m_Dirty = false; - return ret; - } - } - private float m_Distance = 10.0f; - private Vec3f m_Rotation = new Vec3f(); - - public Vec3f LookAtPos = new Vec3f(); - - public override Vec3f Position { get { return m_Camera.Position; } } - public override Vec3f Rotation { get { return m_Rotation; } } + private Vec3f m_LookAt = new Vec3f(); + public Vec3f LookAtPos + { + get { return m_LookAt; } + set { m_LookAt = value; m_Camera.SetPosition(m_LookAt); } + } } class FlyCamera : CameraControls { - public FlyCamera(Camera c) - : base(c) + private Camera m_Camera = null; + + public override Camera Camera { get { return m_Camera; } } + + public FlyCamera() { + m_Camera = Camera.InitFPSLook(); } - public override void Reset(Vec3f pos) + public void Reset(Vec3f position) { - m_Position = pos; + m_Position = position; m_Rotation = new Vec3f(); + + Camera.SetPosition(m_Position); + Camera.SetFPSRotation(m_Rotation); } - public override void Update() + public override bool Update() { + Vec3f pos, fwd, right, up; + m_Camera.GetBasis(out pos, out fwd, out right, out up); + if (CurrentMove[0] != 0) { - Vec3f dir = m_Camera.Right; + Vec3f dir = right; dir.Mul((float)CurrentMove[0]); m_Position.x += dir.x * CurrentSpeed; m_Position.y += dir.y * CurrentSpeed; m_Position.z += dir.z * CurrentSpeed; - - m_Dirty = true; } if (CurrentMove[1] != 0) { Vec3f dir = new Vec3f(0.0f, 1.0f, 0.0f); - //dir = m_Camera.GetUp(); + //dir = up; dir.Mul((float)CurrentMove[1]); m_Position.x += dir.x * CurrentSpeed; m_Position.y += dir.y * CurrentSpeed; m_Position.z += dir.z * CurrentSpeed; - - m_Dirty = true; } if (CurrentMove[2] != 0) { - Vec3f dir = m_Camera.Forward; + Vec3f dir = fwd; dir.Mul((float)CurrentMove[2]); m_Position.x += dir.x * CurrentSpeed; m_Position.y += dir.y * CurrentSpeed; m_Position.z += dir.z * CurrentSpeed; - - m_Dirty = true; } - } - public override void Apply() - { - m_Camera.fpsLook(m_Position, m_Rotation); + if (CurrentMove[0] != 0 || CurrentMove[1] != 0 || CurrentMove[2] != 0) + { + Camera.SetPosition(m_Position); + return true; + } + + return false; } public override void MouseWheel(object sender, MouseEventArgs e) @@ -322,26 +318,13 @@ namespace renderdocui.Code m_Rotation.y -= (float)(e.X - DragStartPos.X) / 300.0f; m_Rotation.x -= (float)(e.Y - DragStartPos.Y) / 300.0f; - m_Dirty = true; + Camera.SetFPSRotation(m_Rotation); } base.MouseMove(sender, e); } - bool m_Dirty = false; - public override bool Dirty - { - get - { - bool ret = m_Dirty; - m_Dirty = false; - return ret; - } - } - - private Vec3f m_Position = new Vec3f(), - m_Rotation = new Vec3f(); - public override Vec3f Position { get { return m_Position; } } - public override Vec3f Rotation { get { return m_Rotation; } } + private Vec3f m_Position = new Vec3f(); + private Vec3f m_Rotation = new Vec3f(); } } diff --git a/renderdocui/Interop/Camera.cs b/renderdocui/Interop/Camera.cs index 381455d0f..349a03416 100644 --- a/renderdocui/Interop/Camera.cs +++ b/renderdocui/Interop/Camera.cs @@ -31,27 +31,103 @@ namespace renderdoc public class Camera { [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] - private static extern void Maths_CameraArcball(ref FloatVector lookat, float dist, ref FloatVector rot, IntPtr pos, IntPtr fwd, IntPtr right, IntPtr up); + private static extern IntPtr Camera_InitArcball(); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr Camera_InitFPSLook(); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void Camera_Shutdown(IntPtr real); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] - private static extern void Maths_CameraFPSLook(ref FloatVector lookpos, ref FloatVector rot, IntPtr pos, IntPtr fwd, IntPtr right, IntPtr up); + private static extern void Camera_SetPosition(IntPtr real, float x, float y, float z); - public void Arcball(Vec3f pos, float dist, Vec3f rot) + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void Camera_SetFPSRotation(IntPtr real, float x, float y, float z); + + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void Camera_SetArcballDistance(IntPtr real, float dist); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void Camera_ResetArcball(IntPtr real); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void Camera_RotateArcball(IntPtr real, float ax, float ay, float bx, float by); + + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void Camera_GetBasis(IntPtr real, IntPtr pos, IntPtr fwd, IntPtr right, IntPtr up); + + private IntPtr m_Real = IntPtr.Zero; + + public IntPtr Real { get { return m_Real; } } + + public static Camera InitArcball() + { + return new Camera(Camera_InitArcball()); + } + + public static Camera InitFPSLook() + { + return new Camera(Camera_InitFPSLook()); + } + + private Camera(IntPtr real) + { + m_Real = real; + } + + public void Shutdown() + { + Camera_Shutdown(m_Real); + } + + public void SetPosition(Vec3f p) + { + Camera_SetPosition(m_Real, p.x, p.y, p.z); + } + + public void SetFPSRotation(Vec3f r) + { + Camera_SetFPSRotation(m_Real, r.x, r.y, r.z); + } + + public void SetArcballDistance(float dist) + { + Camera_SetArcballDistance(m_Real, dist); + } + + public void ResetArcball() + { + Camera_ResetArcball(m_Real); + } + + public void RotateArcball(System.Drawing.Point from, System.Drawing.Point to, System.Drawing.Size winSize) + { + float ax = ((float)from.X / (float)winSize.Width) * 2.0f - 1.0f; + float ay = ((float)from.Y / (float)winSize.Height) * 2.0f - 1.0f; + float bx = ((float)to.X / (float)winSize.Width) * 2.0f - 1.0f; + float by = ((float)to.Y / (float)winSize.Height) * 2.0f - 1.0f; + + // this isn't a 'true arcball' but it handles extreme aspect ratios + // better. We basically 'centre' around the from point always being + // 0,0 (straight out of the screen) as if you're always dragging + // the arcball from the middle, and just use the relative movement + int minDimension = Math.Min(winSize.Width, winSize.Height); + + ax = ay = 0; + bx = ((float)(to.X - from.X) / (float)minDimension) * 2.0f; + by = ((float)(to.Y - from.Y) / (float)minDimension) * 2.0f; + + ay = -ay; + by = -by; + + Camera_RotateArcball(m_Real, ax, ay, bx, by); + } + + public void GetBasis(out Vec3f pos, out Vec3f fwd, out Vec3f right, out Vec3f up) { IntPtr p = CustomMarshal.Alloc(typeof(FloatVector)); IntPtr f = CustomMarshal.Alloc(typeof(FloatVector)); IntPtr r = CustomMarshal.Alloc(typeof(FloatVector)); IntPtr u = CustomMarshal.Alloc(typeof(FloatVector)); - isarc = true; - paramdist = dist; - parampos = pos; - paramrot = new Vec3f(rot); - - var rt = new FloatVector(rot); - var ps = new FloatVector(pos); - - Maths_CameraArcball(ref ps, dist, ref rt, p, f, r, u); + Camera_GetBasis(m_Real, p, f, r, u); pos = new Vec3f((FloatVector)CustomMarshal.PtrToStructure(p, typeof(FloatVector), false)); fwd = new Vec3f((FloatVector)CustomMarshal.PtrToStructure(f, typeof(FloatVector), false)); @@ -63,51 +139,5 @@ namespace renderdoc CustomMarshal.Free(r); CustomMarshal.Free(u); } - public void fpsLook(Vec3f lookpos, Vec3f lookrot) - { - IntPtr p = CustomMarshal.Alloc(typeof(FloatVector)); - IntPtr f = CustomMarshal.Alloc(typeof(FloatVector)); - IntPtr r = CustomMarshal.Alloc(typeof(FloatVector)); - IntPtr u = CustomMarshal.Alloc(typeof(FloatVector)); - - isarc = false; - parampos = new Vec3f(lookpos); - paramrot = new Vec3f(lookrot); - - var ps = new FloatVector(lookpos); - var rt = new FloatVector(lookrot); - - Maths_CameraFPSLook(ref ps, ref rt, p, f, r, u); - - pos = new Vec3f((FloatVector)CustomMarshal.PtrToStructure(p, typeof(FloatVector), false)); - fwd = new Vec3f((FloatVector)CustomMarshal.PtrToStructure(f, typeof(FloatVector), false)); - right = new Vec3f((FloatVector)CustomMarshal.PtrToStructure(r, typeof(FloatVector), false)); - up = new Vec3f((FloatVector)CustomMarshal.PtrToStructure(u, typeof(FloatVector), false)); - - CustomMarshal.Free(p); - CustomMarshal.Free(f); - CustomMarshal.Free(r); - CustomMarshal.Free(u); - } - - private Vec3f pos = new Vec3f(0.0f, 0.0f, 0.0f); - private Vec3f fwd = new Vec3f(0.0f, 0.0f, 1.0f); - private Vec3f right = new Vec3f(1.0f, 0.0f, 0.0f); - private Vec3f up = new Vec3f(0.0f, 1.0f, 0.0f); - - public Vec3f Position { get { return pos; } } - public Vec3f Forward { get { return fwd; } } - public Vec3f Right { get { return right; } } - public Vec3f Up { get { return up; } } - - private bool isarc = false; - private Vec3f parampos = new Vec3f(0.0f, 0.0f, 0.0f); - private float paramdist = 0.0f; - private Vec3f paramrot = new Vec3f(0.0f, 0.0f, 0.0f); - - public bool IsArcball { get { return isarc; } } - public Vec3f PositionParam { get { return parampos; } } - public float DistanceParam { get { return paramdist; } } - public Vec3f RotationParam { get { return paramrot; } } } } diff --git a/renderdocui/Interop/FetchInfo.cs b/renderdocui/Interop/FetchInfo.cs index 3fe9a896d..3862dc9eb 100644 --- a/renderdocui/Interop/FetchInfo.cs +++ b/renderdocui/Interop/FetchInfo.cs @@ -388,9 +388,7 @@ namespace renderdoc { public MeshDataStage type = MeshDataStage.Unknown; - public bool arcballCamera = true; - public FloatVector cameraPos = new FloatVector(); - public FloatVector cameraRot = new FloatVector(); + public IntPtr cam = IntPtr.Zero; public bool ortho = false; public float fov = 90.0f; diff --git a/renderdocui/Windows/BufferViewer.Designer.cs b/renderdocui/Windows/BufferViewer.Designer.cs index 46f09809e..c1e914dea 100644 --- a/renderdocui/Windows/BufferViewer.Designer.cs +++ b/renderdocui/Windows/BufferViewer.Designer.cs @@ -291,18 +291,23 @@ // camSpeed // this.camSpeed.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.camSpeed.DecimalPlaces = 2; + this.camSpeed.DecimalPlaces = 4; this.camSpeed.Increment = new decimal(new int[] { 1, 0, 0, 65536}); this.camSpeed.Location = new System.Drawing.Point(97, 3); + this.camSpeed.Maximum = new decimal(new int[] { + 1000, + 0, + 0, + 0}); this.camSpeed.Minimum = new decimal(new int[] { 1, 0, 0, - 131072}); + 196608}); this.camSpeed.Name = "camSpeed"; this.camSpeed.Size = new System.Drawing.Size(88, 20); this.camSpeed.TabIndex = 12; diff --git a/renderdocui/Windows/BufferViewer.cs b/renderdocui/Windows/BufferViewer.cs index 4ba7287da..af93f17b4 100644 --- a/renderdocui/Windows/BufferViewer.cs +++ b/renderdocui/Windows/BufferViewer.cs @@ -205,8 +205,6 @@ namespace renderdocui.Windows // Cameras private TimedUpdate m_Updater = null; - private Camera m_Camera = new Camera(); - private ArcballCamera m_Arcball = null; private FlyCamera m_Flycam = null; private CameraControls m_CurrentCamera = null; @@ -300,8 +298,13 @@ namespace renderdocui.Windows m_MeshDisplay.currentMeshColour = new FloatVector(1, 0, 0, 1); m_MeshDisplay.prevMeshColour = new FloatVector(0, 0, 0, 1); - m_Arcball = new ArcballCamera(m_Camera); - m_Flycam = new FlyCamera(m_Camera); + if (m_Arcball != null) + m_Arcball.Camera.Shutdown(); + if (m_Flycam != null) + m_Flycam.Camera.Shutdown(); + + m_Arcball = new ArcballCamera(); + m_Flycam = new FlyCamera(); m_CurrentCamera = m_Arcball; m_Updater = new TimedUpdate(10, TimerUpdate); @@ -1930,32 +1933,17 @@ namespace renderdocui.Windows private void resetCam_Click(object sender, EventArgs e) { - m_Arcball.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); - if (m_MeshDisplay.type == MeshDataStage.VSIn) - { - m_Flycam.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); - m_CurrentCamera = m_Arcball; - } - else if(m_MeshDisplay.type == MeshDataStage.VSOut) - { - if (m_Core.CurPipelineState.IsTessellationEnabled) - m_Flycam.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); - else - m_Flycam.Reset(new Vec3f(0.0f, 0.0f, 0.0f)); + controlType.SelectedIndex = 0; + else + controlType.SelectedIndex = 1; - m_CurrentCamera = m_Flycam; - } - else if(m_MeshDisplay.type == MeshDataStage.GSOut) - { - m_Flycam.Reset(new Vec3f(0.0f, 0.0f, 0.0f)); - - m_CurrentCamera = m_Flycam; - } + // make sure callback is called even if we're re-selecting same + // camera type + controlType_SelectedIndexChanged(sender, e); UI_UpdateBoundingBox(); - m_CurrentCamera.Apply(); render.Invalidate(); } @@ -1989,11 +1977,8 @@ namespace renderdocui.Windows m_Flycam.Reset(pos); - camSpeed.Value = Helpers.Clamp((decimal)(diag.Length() / 200.0f), camSpeed.Minimum, camSpeed.Maximum); - UI_UpdateBoundingBox(); - m_CurrentCamera.Apply(); render.Invalidate(); } @@ -2001,13 +1986,10 @@ namespace renderdocui.Windows { if (m_CurrentCamera == null) return; - m_CurrentCamera.Update(); - - if (m_CurrentCamera.Dirty) - { - m_CurrentCamera.Apply(); + if (m_CurrentCamera.Update()) render.Invalidate(); - } + + render.Invalidate(); } private void PickVert(Point p) @@ -2055,12 +2037,16 @@ namespace renderdocui.Windows private void render_MouseWheel(object sender, MouseEventArgs e) { m_CurrentCamera.MouseWheel(sender, e); + + render.Invalidate(); } private void render_MouseMove(object sender, MouseEventArgs e) { m_CurrentCamera.MouseMove(sender, e); + render.Invalidate(); + if (e.Button == MouseButtons.Right) PickVert(e.Location); } @@ -2069,6 +2055,8 @@ namespace renderdocui.Windows { m_CurrentCamera.MouseClick(sender, e); + render.Invalidate(); + if (e.Button == MouseButtons.Right) PickVert(e.Location); } @@ -2085,30 +2073,38 @@ namespace renderdocui.Windows private void controlType_SelectedIndexChanged(object sender, EventArgs e) { + m_Arcball.Reset(new Vec3f(0.0f, 0.0f, 0.0f), 10.0f); + m_Flycam.Reset(new Vec3f(0.0f, 0.0f, 0.0f)); + if (controlType.SelectedIndex == 0) { m_CurrentCamera = m_Arcball; - m_CurrentCamera.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); + m_Arcball.Reset(new Vec3f(0.0f, 0.0f, 0.0f), 10.0f); } else { m_CurrentCamera = m_Flycam; if (m_MeshDisplay.type == MeshDataStage.VSIn) { - m_CurrentCamera.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); + m_Flycam.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); } - else + else if (m_MeshDisplay.type == MeshDataStage.VSOut) { if (m_Core.CurPipelineState.IsTessellationEnabled) - m_CurrentCamera.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); + m_Flycam.Reset(new Vec3f(0.0f, 0.0f, -10.0f)); else - m_CurrentCamera.Reset(new Vec3f(0.0f, 0.0f, 0.0f)); + m_Flycam.Reset(new Vec3f(0.0f, 0.0f, 0.0f)); + } + else if (m_MeshDisplay.type == MeshDataStage.GSOut) + { + m_Flycam.Reset(new Vec3f(0.0f, 0.0f, 0.0f)); + + m_CurrentCamera = m_Flycam; } } UpdateHighlightVerts(GetUIState(m_MeshDisplay.type)); - m_CurrentCamera.Apply(); render.Invalidate(); } @@ -2120,9 +2116,7 @@ namespace renderdocui.Windows { if (m_Output == null) return; - m_MeshDisplay.arcballCamera = m_Camera.IsArcball; - m_MeshDisplay.cameraPos = new FloatVector(m_Camera.PositionParam, m_Camera.DistanceParam); - m_MeshDisplay.cameraRot = new FloatVector(m_Camera.RotationParam); + m_MeshDisplay.cam = m_CurrentCamera.Camera.Real; m_Output.SetMeshDisplay(m_MeshDisplay); } @@ -2417,7 +2411,8 @@ namespace renderdocui.Windows ui.m_MinBounds[CurPosElement].z + diag.z / 2.0f); m_Arcball.SetDistance(diag.Length()*0.7f); - m_CurrentCamera.Apply(); + camSpeed.Value = Helpers.Clamp((decimal)(diag.Length() / 200.0f), camSpeed.Minimum, camSpeed.Maximum); + render.Invalidate(); } }