diff options
Diffstat (limited to 'source/base/StarCellularLighting.hpp')
-rw-r--r-- | source/base/StarCellularLighting.hpp | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/source/base/StarCellularLighting.hpp b/source/base/StarCellularLighting.hpp new file mode 100644 index 0000000..7579a63 --- /dev/null +++ b/source/base/StarCellularLighting.hpp @@ -0,0 +1,96 @@ +#ifndef STAR_CELLULAR_LIGHTING_HPP +#define STAR_CELLULAR_LIGHTING_HPP + +#include "StarEither.hpp" +#include "StarRect.hpp" +#include "StarImage.hpp" +#include "StarJson.hpp" +#include "StarColor.hpp" +#include "StarInterpolation.hpp" +#include "StarCellularLightArray.hpp" + +namespace Star { + +// Produce lighting values from an integral cellular grid. Allows for floating +// positional point and cellular light sources, as well as pre-lighting cells +// individually. +class CellularLightingCalculator { +public: + CellularLightingCalculator(bool monochrome = false); + + typedef ColoredCellularLightArray::Cell Cell; + + void setMonochrome(bool monochrome); + + void setParameters(Json const& config); + + // Call 'begin' to start a calculation for the given region + void begin(RectI const& queryRegion); + + // Once begin is called, this will return the region that could possibly + // affect the target calculation region. All lighting values should be set + // for the given calculation region before calling 'calculate'. + RectI calculationRegion() const; + + size_t baseIndexFor(Vec2I const& position); + + void setCellIndex(size_t cellIndex, Vec3F const& light, bool obstacle); + + void addSpreadLight(Vec2F const& position, Vec3F const& light); + void addPointLight(Vec2F const& position, Vec3F const& light, float beam, float beamAngle, float beamAmbience); + + // Finish the calculation, and put the resulting color data in the given + // output image. The image will be reset to the size of the region given in + // the call to 'begin', and formatted as RGB24. + void calculate(Image& output); + +private: + Json m_config; + bool m_monochrome; + Either<ColoredCellularLightArray, ScalarCellularLightArray> m_lightArray; + RectI m_queryRegion; + RectI m_calculationRegion; +}; + +// Produce light intensity values using the same algorithm as +// CellularLightingCalculator. Only calculates a single point at a time, and +// uses scalar lights with no color calculation. +class CellularLightIntensityCalculator { +public: + typedef ScalarCellularLightArray::Cell Cell; + + void setParameters(Json const& config); + + void begin(Vec2F const& queryPosition); + + RectI calculationRegion() const; + + void setCell(Vec2I const& position, Cell const& cell); + void setCellColumn(Vec2I const& position, Cell const* cells, size_t count); + + void addSpreadLight(Vec2F const& position, float light); + void addPointLight(Vec2F const& position, float light, float beam, float beamAngle, float beamAmbience); + + float calculate(); + +private: + ScalarCellularLightArray m_lightArray; + Vec2F m_queryPosition; + RectI m_queryRegion;; + RectI m_calculationRegion; +}; + +inline size_t CellularLightingCalculator::baseIndexFor(Vec2I const& position) { + return (position[0] - m_calculationRegion.xMin()) * m_calculationRegion.height() + position[1] - m_calculationRegion.yMin(); +} + +inline void CellularLightingCalculator::setCellIndex(size_t cellIndex, Vec3F const& light, bool obstacle) { + if (m_monochrome) + m_lightArray.right().cellAtIndex(cellIndex) = ScalarCellularLightArray::Cell{light.sum() / 3, obstacle}; + else + m_lightArray.left().cellAtIndex(cellIndex) = ColoredCellularLightArray::Cell{light, obstacle}; +} + +} + +#endif |