mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 21:20:07 -05:00
07592c9d78
Add Curves.h, and CurvesGraphicsView.h/cpp to support bezier color curves. Add Curves member to Ember. Add curves capability to EmberCL. Remove some unused variables in the kernel created in RendererCL::CreateFinalAccumKernelString(). Use glm namespace for vec classes if GLM_VERSION >= 96, else use glm::detail. As a result of using glm namespace, all instances of min and max had to be qualified with std:: Split ComputeCamera into that and ComputeQuality(). Reduce the amount of ComputeCamera() and MakeDmap() calls on each incremental iter that doesn't use temporal samples. Fix clamping bug with DE filter widths. Provide functions to return the kernels from RendererCL to assist with diagnostics and debugging. Prevent extra newline in EmberRender when only rendering a single image. Add the ability to delete an ember at a given index in EmberFile. Allow deleting/focusing ember in library tab with delete and enter keys. Reorder some code in Fractorium.h to match the tabs order. Add and call ClearFinalImages() to clear buffers in controller to fix bug where previous CPU render would be shown for a split second when switching from OpenCL back to CPU. Refactor ember library pointer syncing to a function SyncPointers(). Add the ability to save ember Xmls to an unique automatically generated name after the first time the user has specified a name.
272 lines
8.4 KiB
C++
272 lines
8.4 KiB
C++
#include "FractoriumPch.h"
|
|
#include "GLEmberController.h"
|
|
#include "FractoriumEmberController.h"
|
|
#include "Fractorium.h"
|
|
#include "GLWidget.h"
|
|
|
|
/// <summary>
|
|
/// Constructor which assigns pointers to the main window and the GLWidget.
|
|
/// </summary>
|
|
/// <param name="fractorium">Pointer to the main window</param>
|
|
/// <param name="glWidget">Pointer to the GLWidget</param>
|
|
GLEmberControllerBase::GLEmberControllerBase(Fractorium* fractorium, GLWidget* glWidget)
|
|
{
|
|
m_Fractorium = fractorium;
|
|
m_GL = glWidget;
|
|
m_AffineType = AffinePre;
|
|
m_HoverType = HoverNone;
|
|
m_DragState = DragNone;
|
|
m_DragModifier = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Empty destructor which does nothing.
|
|
/// </summary>
|
|
GLEmberControllerBase::~GLEmberControllerBase() { }
|
|
|
|
/// <summary>
|
|
/// Constructor which passes the pointers to the main window the GLWidget to the base,
|
|
/// then assigns the pointer to the parent controller.
|
|
/// </summary>
|
|
/// <param name="fractorium">Pointer to the main window</param>
|
|
/// <param name="glWidget">Pointer to the GLWidget</param>
|
|
/// <param name="controller">Pointer to the parent controller of the same template type</param>
|
|
template <typename T>
|
|
GLEmberController<T>::GLEmberController(Fractorium* fractorium, GLWidget* glWidget, FractoriumEmberController<T>* controller)
|
|
: GLEmberControllerBase(fractorium, glWidget)
|
|
{
|
|
GridStep = T(1.0 / 8.0);
|
|
m_FractoriumEmberController = controller;
|
|
|
|
m_HoverXform = nullptr;
|
|
m_SelectedXform = nullptr;
|
|
m_CenterDownX = 0;
|
|
m_CenterDownY = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Empty destructor which does nothing.
|
|
/// </summary>
|
|
template <typename T>
|
|
GLEmberController<T>::~GLEmberController() { }
|
|
|
|
/// <summary>
|
|
/// Check that the final output size of the current ember matches the dimensions passed in.
|
|
/// </summary>
|
|
/// <param name="w">The width to compare to</param>
|
|
/// <param name="h">The height to compare to</param>
|
|
/// <returns>True if any don't match, else false if they are both equal.</returns>
|
|
template <typename T>
|
|
bool GLEmberController<T>::CheckForSizeMismatch(int w, int h)
|
|
{
|
|
return (m_FractoriumEmberController->FinalRasW() != w || m_FractoriumEmberController->FinalRasH() != h);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset the drag and hover state. Called in response setting a new ember as the current one.
|
|
/// </summary>
|
|
template <typename T>
|
|
void GLEmberController<T>::ResetMouseState()
|
|
{
|
|
m_HoverType = HoverNone;
|
|
m_HoverXform = nullptr;
|
|
m_SelectedXform = nullptr;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate the scale.
|
|
/// Used when dragging the right mouse button.
|
|
/// </summary>
|
|
/// <returns>The distance dragged in pixels</returns>
|
|
template <typename T>
|
|
T GLEmberController<T>::CalcScale()
|
|
{
|
|
//Can't operate using world coords here because every time scale changes, the world bounds change.
|
|
//So must instead calculate distance traveled based on window coords, which do not change outside of resize events.
|
|
v2T windowCenter(T(m_GL->width()) / T(2), T(m_GL->height()) / T(2));
|
|
v2T windowMousePosDistanceFromCenter(m_MousePos.x - windowCenter.x, m_MousePos.y - windowCenter.y);
|
|
v2T windowMouseDownDistanceFromCenter(m_MouseDownPos.x - windowCenter.x, m_MouseDownPos.y - windowCenter.y);
|
|
|
|
T lengthMousePosFromCenterInPixels = glm::length(windowMousePosDistanceFromCenter);
|
|
T lengthMouseDownFromCenterInPixels = glm::length(windowMouseDownDistanceFromCenter);
|
|
|
|
return lengthMousePosFromCenterInPixels - lengthMouseDownFromCenterInPixels;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate the rotation.
|
|
/// Used when dragging the right mouse button.
|
|
/// </summary>
|
|
/// <returns>The angular distance rotated from -180-180</returns>
|
|
template <typename T>
|
|
T GLEmberController<T>::CalcRotation()
|
|
{
|
|
T rotStart = NormalizeDeg180<T>(T(90) - (atan2(-m_MouseDownWorldPos.y, m_MouseDownWorldPos.x) * RAD_2_DEG_T));
|
|
T rot = NormalizeDeg180<T>(T(90) - (atan2(-m_MouseWorldPos.y, m_MouseWorldPos.x) * RAD_2_DEG_T));
|
|
|
|
return rotStart - rot;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Snap the passed in world cartesian coordinate to the grid for rotation, scale or translation.
|
|
/// </summary>
|
|
/// <param name="vec">The world cartesian coordinate to be snapped</param>
|
|
/// <returns>The snapped world cartesian coordinate</returns>
|
|
template <typename T>
|
|
typename v3T GLEmberController<T>::SnapToGrid(v3T& vec)
|
|
{
|
|
v3T ret;
|
|
|
|
ret.x = glm::round(vec.x / GridStep) * GridStep;
|
|
ret.y = glm::round(vec.y / GridStep) * GridStep;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Snap the passed in world cartesian coordinate to the grid for rotation only.
|
|
/// </summary>
|
|
/// <param name="vec">The world cartesian coordinate to be snapped</param>
|
|
/// <param name="divisions">The divisions of a circle to use for snapping</param>
|
|
/// <returns>The snapped world cartesian coordinate</returns>
|
|
template <typename T>
|
|
typename v3T GLEmberController<T>::SnapToNormalizedAngle(v3T& vec, uint divisions)
|
|
{
|
|
T rsq, theta;
|
|
T bestRsq = numeric_limits<T>::max();
|
|
v3T c, best;
|
|
|
|
best.x = 1;
|
|
best.y = 0;
|
|
|
|
for (uint i = 0; i < divisions; i++)
|
|
{
|
|
theta = 2.0 * M_PI * T(i) / T(divisions);
|
|
c.x = cos(theta);
|
|
c.y = sin(theta);
|
|
rsq = glm::distance(vec, c);
|
|
|
|
if (rsq < bestRsq)
|
|
{
|
|
best = c;
|
|
bestRsq = rsq;
|
|
}
|
|
}
|
|
|
|
return best;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert raster window coordinates to world cartesian coordinates.
|
|
/// </summary>
|
|
/// <param name="v">The window coordinates to convert</param>
|
|
/// <param name="flip">True to flip vertically, else don't.</param>
|
|
/// <returns>The converted world cartesian coordinates</returns>
|
|
template <typename T>
|
|
typename v3T GLEmberController<T>::WindowToWorld(v3T& v, bool flip)
|
|
{
|
|
v3T mouse(v.x, flip ? m_Viewport[3] - v.y : v.y, 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
|
v3T newCoords = glm::unProject(mouse, m_Modelview, m_Projection, m_Viewport);//Perform the calculation.
|
|
|
|
newCoords.z = 0;//For some reason, unProject() always comes back with the z coordinate as something other than 0. It should be 0 at all times.
|
|
return newCoords;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Template specialization for querying the viewport, modelview and projection
|
|
/// matrices as floats.
|
|
/// </summary>
|
|
template <>
|
|
void GLEmberController<float>::QueryVMP()
|
|
{
|
|
m_GL->glGetIntegerv(GL_VIEWPORT, glm::value_ptr(m_Viewport));
|
|
m_GL->glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(m_Modelview));
|
|
m_GL->glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(m_Projection));
|
|
}
|
|
|
|
#ifdef DO_DOUBLE
|
|
/// <summary>
|
|
/// Template specialization for querying the viewport, modelview and projection
|
|
/// matrices as doubles.
|
|
/// </summary>
|
|
template <>
|
|
void GLEmberController<double>::QueryVMP()
|
|
{
|
|
m_GL->glGetIntegerv(GL_VIEWPORT, glm::value_ptr(m_Viewport));
|
|
m_GL->glGetDoublev(GL_MODELVIEW_MATRIX, glm::value_ptr(m_Modelview));
|
|
m_GL->glGetDoublev(GL_PROJECTION_MATRIX, glm::value_ptr(m_Projection));
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Template specialization for multiplying the current matrix
|
|
/// by an m4<float>.
|
|
/// </summary>
|
|
template <>
|
|
void GLEmberController<float>::MultMatrix(tmat4x4<float, glm::defaultp>& mat)
|
|
{
|
|
m_GL->glMultMatrixf(glm::value_ptr(mat));
|
|
}
|
|
|
|
#ifdef DO_DOUBLE
|
|
/// <summary>
|
|
/// Template specialization for multiplying the current matrix
|
|
/// by an m4<double>.
|
|
/// </summary>
|
|
template <>
|
|
void GLEmberController<double>::MultMatrix(tmat4x4<double, glm::defaultp>& mat)
|
|
{
|
|
m_GL->glMultMatrixd(glm::value_ptr(mat));
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Query the matrices currently being used.
|
|
/// Debugging function, unused.
|
|
/// </summary>
|
|
/// <param name="print">True to print values, else false.</param>
|
|
template <typename T>
|
|
void GLEmberController<T>::QueryMatrices(bool print)
|
|
{
|
|
RendererBase* renderer = m_FractoriumEmberController->Renderer();
|
|
|
|
if (renderer)
|
|
{
|
|
double unitX = fabs(renderer->UpperRightX(false) - renderer->LowerLeftX(false)) / 2.0;
|
|
double unitY = fabs(renderer->UpperRightY(false) - renderer->LowerLeftY(false)) / 2.0;
|
|
|
|
m_GL->glMatrixMode(GL_PROJECTION);
|
|
m_GL->glPushMatrix();
|
|
m_GL->glLoadIdentity();
|
|
m_GL->glOrtho(-unitX, unitX, -unitY, unitY, -1, 1);
|
|
m_GL->glMatrixMode(GL_MODELVIEW);
|
|
m_GL->glPushMatrix();
|
|
m_GL->glLoadIdentity();
|
|
|
|
QueryVMP();
|
|
|
|
m_GL->glMatrixMode(GL_PROJECTION);
|
|
m_GL->glPopMatrix();
|
|
m_GL->glMatrixMode(GL_MODELVIEW);
|
|
m_GL->glPopMatrix();
|
|
|
|
if (print)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
qDebug() << "Viewport[" << i << "] = " << m_Viewport[i] << endl;
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
qDebug() << "Modelview[" << i << "] = " << glm::value_ptr(m_Modelview)[i] << endl;
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
qDebug() << "Projection[" << i << "] = " << glm::value_ptr(m_Projection)[i] << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
template class GLEmberController<float>;
|
|
|
|
#ifdef DO_DOUBLE
|
|
template class GLEmberController<double>;
|
|
#endif
|