mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 05:00:06 -05:00
1dfbd4eff2
-Add new preset dimensions to the right click menu of the width and height fields in the editor. -Change QSS stylesheets to properly handle tabs. -Make tabs rectangular by default. For some reason, they had always been triangular. --Bug fixes -Incremental rendering times in the editor were wrong. --Code changes -Migrate to Qt6. There is probably more work to be done here. -Migrate to VS2022. -Migrate to Wix 4 installer. -Change installer to install to program files for all users. -Fix many VS2022 code analysis warnings. -No longer use byte typedef, because std::byte is now a type. Revert all back to unsigned char. -Upgrade OpenCL headers to version 3.0 and keep locally now rather than trying to look for system files. -No longer link to Nvidia or AMD specific OpenCL libraries. Use the generic installer located at OCL_ROOT too. -Add the ability to change OpenCL grid dimensions. This was attempted for investigating possible performance improvments, but made no difference. This has not been verified on Linux or Mac yet.
274 lines
13 KiB
C++
274 lines
13 KiB
C++
#pragma once
|
|
|
|
#include "Point.h"
|
|
|
|
/// <summary>
|
|
/// CarToRas class.
|
|
/// </summary>
|
|
|
|
namespace EmberNs
|
|
{
|
|
/// <summary>
|
|
/// When iterating, everything is positioned in terms of a carteseian plane with 0,0 in the center like so:
|
|
/// [-1,1] [1,1]
|
|
/// [-1,-1] [1,-1]
|
|
/// However, when accumulating to the histogram, the data is stored in the traditional raster coordinate system
|
|
/// of 0,0 at the top left and x,y at the bottom right. This class provides functionality to convert from one
|
|
/// to the other and is used when accumulating a sub batch of iteration results to the histogram.
|
|
/// Note the functions use reference arguments for the converted values because they are slightly faster than returning a value.
|
|
/// Template argument expected to be float or double.
|
|
/// </summary>
|
|
template <typename T>
|
|
class EMBER_API CarToRas
|
|
{
|
|
public:
|
|
/// <summary>
|
|
/// Empty constructor. This class should never be used unless it's been properly constructed with the constructor that takes arguments.
|
|
/// </summary>
|
|
CarToRas() = default;
|
|
|
|
/// <summary>
|
|
/// Constructor that takes arguments to set up the bounds and passes them to Init().
|
|
/// </summary>
|
|
/// <param name="carLlX">The lower left x of the cartesian plane</param>
|
|
/// <param name="carLlY">The lower left y of the cartesian plane</param>
|
|
/// <param name="carUrX">The upper right x of the cartesian plane</param>
|
|
/// <param name="carUrY">The upper right y of the cartesian plane</param>
|
|
/// <param name="rasW">The width in pixels of the raster image/histogram</param>
|
|
/// <param name="rasH">The height in pixels of the raster image/histogram</param>
|
|
/// <param name="aspectRatio">The aspect ratio, generally 1</param>
|
|
CarToRas(T carLlX, T carLlY, T carUrX, T carUrY, size_t rasW, size_t rasH, T aspectRatio)
|
|
{
|
|
Init(carLlX, carLlY, carUrX, carUrY, rasW, rasH, aspectRatio);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Default copy constructor.
|
|
/// </summary>
|
|
/// <param name="carToRas">The CarToRas object to copy</param>
|
|
CarToRas(const CarToRas<T>& carToRas)
|
|
{
|
|
CarToRas<T>::operator=<T>(carToRas);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy constructor to copy a CarToRas object of type U.
|
|
/// </summary>
|
|
/// <param name="carToRas">The CarToRas object to copy</param>
|
|
template <typename U>
|
|
CarToRas(const CarToRas<U>& carToRas)
|
|
{
|
|
CarToRas<T>::operator=<U>(carToRas);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Default assignment operator.
|
|
/// </summary>
|
|
/// <param name="carToRas">The CarToRas object to copy</param>
|
|
CarToRas<T>& operator = (const CarToRas<T>& carToRas)
|
|
{
|
|
if (this != &carToRas)
|
|
CarToRas<T>::operator=<T>(carToRas);
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assignment operator to assign a CarToRas object of type U.
|
|
/// </summary>
|
|
/// <param name="carToRas">The CarToRas object to copy.</param>
|
|
/// <returns>Reference to updated self</returns>
|
|
template <typename U>
|
|
CarToRas<T>& operator = (const CarToRas<U>& carToRas)
|
|
{
|
|
m_RasWidth = carToRas.RasWidth();
|
|
m_RasHeight = carToRas.RasHeight();
|
|
m_OneRow = T(carToRas.OneRow());
|
|
m_OneCol = T(carToRas.OneCol());
|
|
m_PixPerImageUnitW = T(carToRas.PixPerImageUnitW());
|
|
m_RasLlX = T(carToRas.RasLlX());
|
|
m_PixPerImageUnitH = T(carToRas.PixPerImageUnitH());
|
|
m_RasLlY = T(carToRas.RasLlY());
|
|
m_CarLlX = T(carToRas.CarLlX());
|
|
m_CarLlY = T(carToRas.CarLlY());
|
|
m_CarUrX = T(carToRas.CarUrX());
|
|
m_CarUrY = T(carToRas.CarUrY());
|
|
m_PadCarLlX = T(carToRas.PadCarLlX());
|
|
m_PadCarLlY = T(carToRas.PadCarLlY());
|
|
m_PadCarUrX = T(carToRas.PadCarUrX());
|
|
m_PadCarUrY = T(carToRas.PadCarUrY());
|
|
m_CarHalfX = T(carToRas.CarHalfX());
|
|
m_CarHalfY = T(carToRas.CarHalfY());
|
|
m_CarCenterX = T(carToRas.CarCenterX());
|
|
m_CarCenterY = T(carToRas.CarCenterY());
|
|
return *this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize the dimensions with the specified bounds.
|
|
/// </summary>
|
|
/// <param name="carLlX">The lower left x of the cartesian plane</param>
|
|
/// <param name="carLlY">The lower left y of the cartesian plane</param>
|
|
/// <param name="carUrX">The upper right x of the cartesian plane</param>
|
|
/// <param name="carUrY">The upper right y of the cartesian plane</param>
|
|
/// <param name="rasW">The width in pixels of the raster image/histogram</param>
|
|
/// <param name="rasH">The height in pixels of the raster image/histogram</param>
|
|
/// <param name="aspectRatio">The aspect ratio, generally 1</param>
|
|
void Init(T carLlX, T carLlY, T carUrX, T carUrY, size_t rasW, size_t rasH, T aspectRatio)
|
|
{
|
|
m_RasWidth = rasW;
|
|
m_RasHeight = rasH;
|
|
m_CarLlX = carLlX;
|
|
m_CarLlY = carLlY;
|
|
m_CarUrX = carUrX;
|
|
m_CarUrY = carUrY;
|
|
T carW = m_CarUrX - m_CarLlX;//Right minus left.
|
|
T carH = m_CarUrY - m_CarLlY;//Top minus bottom.
|
|
T invSizeW = T(1.0) / carW;
|
|
T invSizeH = T(1.0) / carH;
|
|
m_PixPerImageUnitW = static_cast<T>(rasW) * invSizeW;
|
|
m_RasLlX = m_PixPerImageUnitW * carLlX;
|
|
m_PixPerImageUnitH = static_cast<T>(rasH) * invSizeH;
|
|
m_RasLlY = m_PixPerImageUnitH * carLlY;
|
|
m_OneRow = std::abs(m_CarUrY - m_CarLlY) / m_RasHeight;
|
|
m_OneCol = std::abs(m_CarUrX - m_CarLlX) / m_RasWidth;
|
|
m_PadCarLlX = m_CarLlX + m_OneCol;
|
|
m_PadCarUrX = m_CarUrX - m_OneCol;
|
|
m_PadCarLlY = m_CarLlY + m_OneRow;
|
|
m_PadCarUrY = m_CarUrY - m_OneRow;
|
|
m_CarHalfX = (m_CarUrX - m_CarLlX) / 2;
|
|
m_CarHalfY = (m_CarUrY - m_CarLlY) / 2;
|
|
m_CarCenterX = m_CarLlX + m_CarHalfX;
|
|
m_CarCenterY = m_CarLlY + m_CarHalfY;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assign values to the cached half width/height fields.
|
|
/// This is only done manually here and is used when rendering strips
|
|
/// because a cached copy of these is required because the real values
|
|
/// change with the assignment of each temporary strip ember object.
|
|
/// </summary>
|
|
/// <param name="x">The cached value equal to half of the cartesian width of the x plane</param>
|
|
/// <param name="y">The cached value equal to half of the cartesian width of the y plane</param>
|
|
void UpdateCachedHalf(T x, T y)
|
|
{
|
|
m_CachedCarHalfX = x;
|
|
m_CachedCarHalfY = y;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a cartesian x, y coordinate to a raster x, y coordinate.
|
|
/// This will flip the Y coordinate, so points that hit the bottom of the cartesian plane will
|
|
/// be mapped to the top of the histogram and vice versa.
|
|
/// There is a very slim chance that a point will be right on the border and will technically be in bounds, passing the InBounds() test,
|
|
/// but ends up being mapped to a histogram bucket that is out of bounds due to roundoff error. Perform an additional check after this call to make sure the
|
|
/// mapped point is in bounds.
|
|
/// </summary>
|
|
/// <param name="cartX">The cartesian x</param>
|
|
/// <param name="cartY">The cartesian y</param>
|
|
/// <param name="rasX">The converted raster x</param>
|
|
/// <param name="rasY">The converted raster y</param>
|
|
inline void Convert(T cartX, T cartY, size_t& rasX, size_t& rasY)
|
|
{
|
|
rasX = static_cast<size_t>(m_PixPerImageUnitW * cartX - m_RasLlX);
|
|
rasY = static_cast<size_t>(m_RasLlY - (m_PixPerImageUnitH * cartY));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a cartesian x, y coordinate to a single raster buffer index.
|
|
/// This will flip the Y coordinate, so points that hit the bottom of the cartesian plane will
|
|
/// be mapped to the top of the histogram and vice versa.
|
|
/// There is a very slim chance that a point will be right on the border and will technically be in bounds, passing the InBounds() test,
|
|
/// but ends up being mapped to a histogram bucket that is out of bounds due to roundoff error. Perform an additional check after this call to make sure the
|
|
/// mapped point is in bounds.
|
|
/// </summary>
|
|
/// <param name="cartX">The cartesian x</param>
|
|
/// <param name="cartY">The cartesian y</param>
|
|
/// <param name="singleBufferIndex">The converted single raster buffer index</param>
|
|
inline void Convert(T cartX, T cartY, size_t& singleBufferIndex)
|
|
{
|
|
singleBufferIndex = static_cast<size_t>(m_PixPerImageUnitW * cartX - m_RasLlX) + (m_RasWidth * static_cast<size_t>(m_PixPerImageUnitH * cartY - m_RasLlY));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a cartesian x, y point to a single raster buffer index.
|
|
/// This will flip the Y coordinate, so points that hit the bottom of the cartesian plane will
|
|
/// be mapped to the top of the histogram and vice versa.
|
|
/// This is the most efficient possible way of converting, consisting of only
|
|
/// a multiply and subtract per coordinate element.
|
|
/// There is a very slim chance that a point will be right on the border and will technically be in bounds, passing the InBounds() test,
|
|
/// but ends up being mapped to a histogram bucket that is out of bounds due to roundoff error. Perform an additional check after this call to make sure the
|
|
/// mapped point is in bounds.
|
|
/// </summary>
|
|
/// <param name="point">The cartesian y</param>
|
|
/// <param name="singleBufferIndex">The converted single raster buffer index</param>
|
|
inline void Convert(Point<T>& point, size_t& singleBufferIndex)
|
|
{
|
|
//singleBufferIndex = static_cast<size_t>(Round(m_PixPerImageUnitW * point.m_X - m_RasLlX) + (m_RasWidth * Round(m_PixPerImageUnitH * point.m_Y - m_RasLlY)));
|
|
singleBufferIndex = static_cast<size_t>(m_PixPerImageUnitW * point.m_X - m_RasLlX) + (m_RasWidth * static_cast<size_t>(m_PixPerImageUnitH * point.m_Y - m_RasLlY));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determine if a point in the cartesian plane can be converted to a point within the raster plane.
|
|
/// There is a very slim chance that a point will be right on the border and will technically be in bounds, passing the InBounds() test,
|
|
/// but ends up being mapped to a histogram bucket that is out of bounds due to roundoff error. Perform an additional check after this call to make sure the
|
|
/// mapped point is in bounds.
|
|
/// </summary>
|
|
/// <param name="point">The point to test</param>
|
|
/// <returns>True if within bounds, else false</returns>
|
|
inline bool InBounds(Point<T>& point)
|
|
{
|
|
//Debug check for hitting the very first pixel in the image.
|
|
//if (point.m_Y > m_CarLlY && point.m_Y <= m_PadCarLlY && //Mapped to top row...
|
|
// point.m_X > m_CarLlX && point.m_X <= m_PadCarLlX)//...first col.
|
|
//{
|
|
// cout << "First pixel hit.\n";
|
|
//}
|
|
return point.m_X >= m_CarLlX &&
|
|
point.m_X < m_CarUrX &&
|
|
point.m_Y < m_CarUrY &&
|
|
point.m_Y >= m_CarLlY;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Accessors.
|
|
/// </summary>
|
|
inline size_t RasWidth() const { return m_RasWidth; }
|
|
inline size_t RasHeight() const { return m_RasHeight; }
|
|
inline T OneRow() const { return m_OneRow; }
|
|
inline T OneCol() const { return m_OneCol; }
|
|
inline T PixPerImageUnitW() const { return m_PixPerImageUnitW; }
|
|
inline T RasLlX() const { return m_RasLlX; }
|
|
inline T PixPerImageUnitH() const { return m_PixPerImageUnitH; }
|
|
inline T RasLlY() const { return m_RasLlY; }
|
|
inline T CarLlX() const { return m_CarLlX; }
|
|
inline T CarLlY() const { return m_CarLlY; }
|
|
inline T CarUrX() const { return m_CarUrX; }
|
|
inline T CarUrY() const { return m_CarUrY; }
|
|
inline T PadCarLlX() const { return m_PadCarLlX; }
|
|
inline T PadCarLlY() const { return m_PadCarLlY; }
|
|
inline T PadCarUrX() const { return m_PadCarUrX; }
|
|
inline T PadCarUrY() const { return m_PadCarUrY; }
|
|
inline T CarHalfX() const { return m_CarHalfX; }
|
|
inline T CarHalfY() const { return m_CarHalfY; }
|
|
inline T CachedCarHalfX() const { return m_CachedCarHalfX; }
|
|
inline T CachedCarHalfY() const { return m_CachedCarHalfY; }
|
|
inline T CarCenterX() const { return m_CarCenterX; }
|
|
inline T CarCenterY() const { return m_CarCenterY; }
|
|
|
|
private:
|
|
size_t m_RasWidth, m_RasHeight;//The width and height of the raster image.
|
|
T m_OneRow;//The distance that one raster row represents in the cartesian plane.
|
|
T m_OneCol;//The distance that one raster column represents in the cartesian plane.
|
|
T m_PixPerImageUnitW;//The number of columns in the raster plane that a horizontal distance of 1 in the cartesian plane represents. The higher the number, the more zoomed in.
|
|
T m_RasLlX;//The lower left x of the raster image plane.
|
|
T m_PixPerImageUnitH;//The number of rows in the raster plane that a vertical distance of 1 in the cartesian plane represents. The higher the number, the more zoomed in.
|
|
T m_RasLlY;//The lower left y of the raster image plane.
|
|
T m_CarLlX, m_CarLlY, m_CarUrX, m_CarUrY;//The bounds of the cartesian plane.
|
|
T m_PadCarLlX, m_PadCarLlY, m_PadCarUrX, m_PadCarUrY;//The bounds of the cartesian plane padded by one raster row and column on each side.
|
|
T m_CarHalfX, m_CarHalfY;//The distance from the center of the of the cartesian plane to the edges.
|
|
T m_CachedCarHalfX, m_CachedCarHalfY;//The cahced distance from the center of the of the cartesian plane to the edges, needed when rendering strips.
|
|
T m_CarCenterX, m_CarCenterY;//The center of the cartesian plane.
|
|
};
|
|
}
|