diff --git a/Makefile b/Makefile index 85e81fa..ea77449 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BUILDMODE=release BUILDPATH=./build/${BUILDMODE} -LIBRARY_PATH=${BUILDPATH}/rendering:${BUILDPATH}/exploring:${BUILDPATH}/system:${BUILDPATH}/basics:${BUILDPATH}/definition:${BUILDPATH}/tests/googletest +LIBRARY_PATH=${BUILDPATH}/rendering:${BUILDPATH}/exploring:${BUILDPATH}/system:${BUILDPATH}/basics:${BUILDPATH}/definition:${BUILDPATH}/render/opengl:${BUILDPATH}/render/software:${BUILDPATH}/tests/googletest all:build @@ -33,7 +33,11 @@ release: +make BUILDMODE=release all tests:build +ifdef TESTCASE + LD_LIBRARY_PATH=$(LIBRARY_PATH) ${BUILDPATH}/tests/paysages-tests --gtest_filter=$(TESTCASE).* +else LD_LIBRARY_PATH=$(LIBRARY_PATH) ${BUILDPATH}/tests/paysages-tests +endif run_cli:build LD_LIBRARY_PATH=$(LIBRARY_PATH) ${RUNNER} ${BUILDPATH}/controlling/paysages-cli @@ -56,6 +60,10 @@ package:release mkdir paysages3d-linux/lib mkdir paysages3d-linux/cache cp $(BUILDPATH)/system/libpaysages_system.so* paysages3d-linux/lib/ + cp $(BUILDPATH)/basics/libpaysages_basics.so* paysages3d-linux/lib/ + cp $(BUILDPATH)/definition/libpaysages_definition.so* paysages3d-linux/lib/ + cp $(BUILDPATH)/render/software/libpaysages_render_software.so* paysages3d-linux/lib/ + cp $(BUILDPATH)/render/opengl/libpaysages_render_opengl.so* paysages3d-linux/lib/ cp $(BUILDPATH)/rendering/libpaysages_rendering.so* paysages3d-linux/lib/ cp $(BUILDPATH)/exploring/libpaysages_exploring.so* paysages3d-linux/lib/ cp $(BUILDPATH)/editing/paysages-gui paysages3d-linux/lib/ diff --git a/src/basics/SpaceSegment.cpp b/src/basics/SpaceSegment.cpp new file mode 100644 index 0000000..2e718d1 --- /dev/null +++ b/src/basics/SpaceSegment.cpp @@ -0,0 +1,56 @@ +#include "SpaceSegment.h" + +SpaceSegment::SpaceSegment(const Vector3& start, const Vector3& end): + start(start), end(end) +{ +} + +bool SpaceSegment::intersectYInterval(double ymin, double ymax) +{ + if (start.y > ymax) + { + if (end.y >= ymax) + { + return false; + } + else + { + Vector3 diff = end.sub(start); + start = start.add(diff.scale((ymax - start.y) / diff.y)); + if (end.y < ymin) + { + end = end.add(diff.scale((ymin - end.y) / diff.y)); + } + } + } + else if (start.y < ymin) + { + if (end.y <= ymin) + { + return false; + } + else + { + Vector3 diff = end.sub(start); + start = start.add(diff.scale((ymin - start.y) / diff.y)); + if (end.y >= ymax) + { + end = end.add(diff.scale((ymax - end.y) / diff.y)); + } + } + } + else /* start is inside layer */ + { + Vector3 diff = end.sub(start); + if (end.y > ymax) + { + end = start.add(diff.scale((ymax - start.y) / diff.y)); + } + else if (end.y < ymin) + { + end = start.add(diff.scale((ymin - start.y) / diff.y)); + } + } + + return true; +} diff --git a/src/basics/SpaceSegment.h b/src/basics/SpaceSegment.h new file mode 100644 index 0000000..d7220ef --- /dev/null +++ b/src/basics/SpaceSegment.h @@ -0,0 +1,39 @@ +#ifndef SPACESEGMENT_H +#define SPACESEGMENT_H + +#include "basics_global.h" + +#include "Vector3.h" + +namespace paysages +{ +namespace basics +{ + +/*! + * \brief A segment in 3D space (mainly useful for rays). + */ +class SpaceSegment +{ +public: + SpaceSegment(const Vector3& start, const Vector3& end); + SpaceSegment(): SpaceSegment(Vector3(), Vector3()) {} + + inline Vector3 getStart() const {return start;} + inline Vector3 getEnd() const {return end;} + + /*! + * \brief Keep only the intersection with a slice orthogonal to the Y axis. + * \return true if a segment remains + */ + bool intersectYInterval(double ymin, double ymax); + +private: + Vector3 start; + Vector3 end; +}; + +} +} + +#endif // SPACESEGMENT_H diff --git a/src/basics/Vector3.cpp b/src/basics/Vector3.cpp new file mode 100644 index 0000000..c7b413f --- /dev/null +++ b/src/basics/Vector3.cpp @@ -0,0 +1,78 @@ +#include "Vector3.inline.cpp" + +#include +#include "PackStream.h" + +const Vector3 paysages::basics::VECTOR_ZERO(0.0, 0.0, 0.0); +const Vector3 paysages::basics::VECTOR_DOWN(0.0, -1.0, 0.0); +const Vector3 paysages::basics::VECTOR_UP(0.0, 1.0, 0.0); +const Vector3 paysages::basics::VECTOR_NORTH(0.0, 0.0, -1.0); +const Vector3 paysages::basics::VECTOR_SOUTH(0.0, 0.0, 1.0); +const Vector3 paysages::basics::VECTOR_WEST(-1.0, 0.0, 0.0); +const Vector3 paysages::basics::VECTOR_EAST(1.0, 0.0, 0.0); + +Vector3::Vector3(const VectorSpherical &v): + x(v.r * cos(v.phi) * cos(v.theta)), y(v.r * sin(v.theta)), z(-v.r * sin(v.phi) * cos(v.theta)) +{ +} + +void Vector3::save(PackStream* stream) const +{ + stream->write(&x); + stream->write(&y); + stream->write(&z); +} +void Vector3::load(PackStream* stream) +{ + stream->read(&x); + stream->read(&y); + stream->read(&z); +} + +static inline double _euclidGet2DAngle(double x, double y) +{ + // TEMP Copy of old euclid.c + double nx, ny, d, ret; + + if (x == 0.0) + { + if (y == 0.0) + { + return 0.0; + } + else if (y < 0.0) + { + return 3.0 * M_PI_2; + } + else + { + return M_PI_2; + } + } + + d = sqrt(x * x + y * y); + nx = x / d; + ny = y / d; + + ret = asin(ny); + if (nx < 0.0) + { + ret = M_PI - ret; + } + return ret < 0.0 ? ret + 2.0 * M_PI : ret; +} + +VectorSpherical Vector3::toSpherical() const +{ + VectorSpherical result; + + result.phi = _euclidGet2DAngle(x, -z); + result.theta = _euclidGet2DAngle(sqrt(x * x + z * z), y); + if (y < 0.0) + { + result.theta -= 2.0 * M_PI; + } + result.r = getNorm(); + + return result; +} diff --git a/src/basics/Vector3.h b/src/basics/Vector3.h new file mode 100644 index 0000000..b5a0ab7 --- /dev/null +++ b/src/basics/Vector3.h @@ -0,0 +1,150 @@ +#ifndef VECTOR3_H +#define VECTOR3_H + +#include "basics_global.h" + +namespace paysages { +namespace basics { + +/* + * Cartesian coordinates (X, Y, Z) - right handed : + * + * Y (up) + * | + * | + * +----X + * / + * / + * Z + * + * Spherical coordinates (R, PHI, THETA) : + * + * R is the distance to origin + * PHI is typical azimuth + * THETA is elevation angle (not polar angle!) + * + * X=1 Y=0 Z=0 => PHI=0 + * X=0 Y=0 Z=-1 => PHI=PI/2 + * X=-1 Y=0 Z=0 => PHI=PI + * X=0 Y=0 Z=1 => PHI=3*PI/2 + * + * X=1 Y=0 Z=0 => THETA=0 + * X=0 Y=1 Z=0 => THETA=PI/2 + * X=0 Y=-1 Z=0 => THETA=-PI/2 + */ + +typedef struct +{ + double r; + double theta; + double phi; +} VectorSpherical; + +class BASICSSHARED_EXPORT Vector3 +{ +public: + Vector3(); + Vector3(double x, double y, double z); + Vector3(const VectorSpherical &v); + + void save(PackStream *stream) const; + void load(PackStream *stream); + + Vector3 inverse() const; + Vector3 scale(double scaling) const; + double getNorm() const; + Vector3 normalize() const; + + Vector3 add(double x, double y, double z) const; + Vector3 add(const Vector3 &other) const; + Vector3 sub(const Vector3 &other) const; + double dotProduct(const Vector3 &other) const; + Vector3 crossProduct(const Vector3 &other) const; + + VectorSpherical toSpherical() const; + +public: + // TODO Make private + double x; + double y; + double z; +}; + +BASICSSHARED_EXPORT extern const Vector3 VECTOR_ZERO; +BASICSSHARED_EXPORT extern const Vector3 VECTOR_DOWN; +BASICSSHARED_EXPORT extern const Vector3 VECTOR_UP; +BASICSSHARED_EXPORT extern const Vector3 VECTOR_NORTH; +BASICSSHARED_EXPORT extern const Vector3 VECTOR_SOUTH; +BASICSSHARED_EXPORT extern const Vector3 VECTOR_EAST; +BASICSSHARED_EXPORT extern const Vector3 VECTOR_WEST; + +} +} + +// Inlining +#if PAYSAGES_USE_INLINING +#ifndef VECTOR3_INLINE_CPP +#include "Vector3.inline.cpp" +#endif +#endif + +// Compat API + +static inline Vector3 v3(double x, double y, double z) +{ + return Vector3(x, y, z); +} +static inline void v3Save(PackStream* stream, Vector3* v) +{ + v->save(stream); +} +static inline void v3Load(PackStream* stream, Vector3* v) +{ + v->load(stream); +} +static inline Vector3 v3Translate(const Vector3 &v1, double x, double y, double z) +{ + return v1.add(x, y, z); +} +static inline Vector3 v3Add(const Vector3 &v1, const Vector3 &v2) +{ + return v1.add(v2); +} +static inline Vector3 v3Sub(const Vector3 &v1, const Vector3 &v2) +{ + return v1.sub(v2); +} +static inline Vector3 v3Neg(const Vector3 &v) +{ + return v.inverse(); +} +static inline Vector3 v3Scale(const Vector3 &v, double scale) +{ + return v.scale(scale); +} +static inline double v3Norm(const Vector3 &v) +{ + return v.getNorm(); +} +static inline Vector3 v3Normalize(const Vector3 &v) +{ + return v.normalize(); +} +static inline double v3Dot(const Vector3 &v1, const Vector3 &v2) +{ + return v1.dotProduct(v2); +} +static inline Vector3 v3Cross(const Vector3 &v1, const Vector3 &v2) +{ + return v1.crossProduct(v2); +} +static inline VectorSpherical v3ToSpherical(const Vector3 &v) +{ + return v.toSpherical(); +} +static inline Vector3 v3FromSpherical(const VectorSpherical &v) +{ + return Vector3(v); +} + +#endif // VECTOR3_H diff --git a/src/basics/Vector3.inline.cpp b/src/basics/Vector3.inline.cpp new file mode 100644 index 0000000..2e9b12c --- /dev/null +++ b/src/basics/Vector3.inline.cpp @@ -0,0 +1,78 @@ +#define VECTOR3_INLINE_CPP + +#ifdef VECTOR3_H +# define METHSPEC inline +#else +# include "Vector3.h" +# define METHSPEC +#endif + +#include + +METHSPEC Vector3::Vector3(double x, double y, double z): + x(x), y(y), z(z) +{ +} + +METHSPEC Vector3::Vector3(): + x(0.0), y(0.0), z(0.0) +{ +} + +METHSPEC Vector3 Vector3::add(double x, double y, double z) const +{ + return Vector3(this->x + x, this->y + y, this->z + z); +} + +METHSPEC Vector3 Vector3::add(const Vector3 &other) const +{ + return Vector3(x + other.x, y + other.y, z + other.z); +} + +METHSPEC Vector3 Vector3::sub(const Vector3 &other) const +{ + return Vector3(x - other.x, y - other.y, z - other.z); +} + +METHSPEC Vector3 Vector3::inverse() const +{ + return Vector3(-x, -y, -z); +} + +METHSPEC Vector3 Vector3::scale(double scaling) const +{ + return Vector3(x * scaling, y * scaling, z * scaling); +} + +METHSPEC double Vector3::getNorm() const +{ + return sqrt(x * x + y * y + z * z); +} + +METHSPEC Vector3 Vector3::normalize() const +{ + double norm = sqrt(x * x + y * y + z * z); + if (norm == 0.0) + { + return VECTOR_ZERO; + } + else + { + norm = 1.0 / norm; + return Vector3(x * norm, y * norm, z * norm); + } +} + +METHSPEC double Vector3:: dotProduct(const Vector3 &other) const +{ + return x * other.x + y * other.y + z * other.z; +} + +METHSPEC Vector3 Vector3::crossProduct(const Vector3 &other) const +{ + return Vector3( + y * other.z - z * other.y, + z * other.x - x * other.z, + x * other.y - y * other.x + ); +} diff --git a/src/basics/basics.pro b/src/basics/basics.pro index 6cc300a..8801948 100644 --- a/src/basics/basics.pro +++ b/src/basics/basics.pro @@ -11,12 +11,17 @@ TEMPLATE = lib DEFINES += BASICS_LIBRARY +include(../common.pri) + SOURCES += \ NoiseGenerator.cpp \ NoiseFunctionNaive.cpp \ NoiseFunctionPerlin.cpp \ NoiseFunctionSimplex.cpp \ - Interpolation.cpp + Interpolation.cpp \ + Vector3.cpp \ + Vector3.inline.cpp \ + SpaceSegment.cpp HEADERS +=\ basics_global.h \ @@ -24,7 +29,9 @@ HEADERS +=\ NoiseFunctionNaive.h \ NoiseFunctionPerlin.h \ NoiseFunctionSimplex.h \ - Interpolation.h + Interpolation.h \ + Vector3.h \ + SpaceSegment.h unix:!symbian { maemo5 { diff --git a/src/basics/basics_global.h b/src/basics/basics_global.h index 9c05c66..81b7fc8 100644 --- a/src/basics/basics_global.h +++ b/src/basics/basics_global.h @@ -1,21 +1,21 @@ #ifndef BASICS_GLOBAL_H #define BASICS_GLOBAL_H -/* Shared object helpers */ #include -#if defined(DEFINITION_LIBRARY) +#if defined(BASICS_LIBRARY) # define BASICSSHARED_EXPORT Q_DECL_EXPORT #else # define BASICSSHARED_EXPORT Q_DECL_IMPORT #endif -/* Namespace using */ -namespace paysages -{ - namespace system {} - namespace basics {} +#include "system_global.h" + +namespace paysages { +namespace basics { + class Vector3; + class SpaceSegment; +} } -using namespace paysages::system; using namespace paysages::basics; #endif // BASICS_GLOBAL_H diff --git a/src/common.pri b/src/common.pri new file mode 100644 index 0000000..db8cca7 --- /dev/null +++ b/src/common.pri @@ -0,0 +1,3 @@ +CONFIG(release, debug|release): DEFINES += NDEBUG + +QMAKE_CXXFLAGS += -std=c++11 diff --git a/src/controlling/controlling.pro b/src/controlling/controlling.pro index f1ffd65..e138638 100644 --- a/src/controlling/controlling.pro +++ b/src/controlling/controlling.pro @@ -6,7 +6,7 @@ TARGET = paysages-cli INCLUDEPATH += $$PWD/.. -CONFIG(release, debug|release): DEFINES += NDEBUG +include(../common.pri) SOURCES += \ main.cpp diff --git a/src/definition/definition.pro b/src/definition/definition.pro index 39c6b65..dbf85a5 100644 --- a/src/definition/definition.pro +++ b/src/definition/definition.pro @@ -11,6 +11,8 @@ TEMPLATE = lib DEFINES += DEFINITION_LIBRARY +include(../common.pri) + SOURCES += \ BaseDefinition.cpp \ Layers.cpp \ diff --git a/src/editing/editing.pro b/src/editing/editing.pro index 10f3ca9..de3ef27 100644 --- a/src/editing/editing.pro +++ b/src/editing/editing.pro @@ -7,7 +7,7 @@ TARGET = paysages-gui unix:LIBS += -lGLU -CONFIG(release, debug|release): DEFINES += NDEBUG +include(../common.pri) INCLUDEPATH += $$PWD/.. @@ -161,6 +161,12 @@ else:unix: LIBS += -L$$OUT_PWD/../definition/ -lpaysages_definition INCLUDEPATH += $$PWD/../definition DEPENDPATH += $$PWD/../definition +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../render/software/release/ -lpaysages_render_software +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../render/software/debug/ -lpaysages_render_software +else:unix: LIBS += -L$$OUT_PWD/../render/software/ -lpaysages_render_software +INCLUDEPATH += $$PWD/../render/software +DEPENDPATH += $$PWD/../render/software + win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../render/opengl/release/ -lpaysages_render_opengl else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../render/opengl/debug/ -lpaysages_render_opengl else:unix: LIBS += -L$$OUT_PWD/../render/opengl/ -lpaysages_render_opengl diff --git a/src/editing/editing_global.h b/src/editing/editing_global.h index c2a39ad..09e2e46 100644 --- a/src/editing/editing_global.h +++ b/src/editing/editing_global.h @@ -6,11 +6,13 @@ namespace paysages namespace system {} namespace basics {} namespace definition {} + namespace software {} namespace opengl {} } using namespace paysages::system; using namespace paysages::basics; using namespace paysages::definition; +using namespace paysages::software; using namespace paysages::opengl; #endif // EDITING_GLOBAL_H diff --git a/src/editing/formrender.cpp b/src/editing/formrender.cpp index 5a79478..3f00179 100644 --- a/src/editing/formrender.cpp +++ b/src/editing/formrender.cpp @@ -12,6 +12,7 @@ #include "rendering/water/public.h" #include "Scenery.h" #include "PackStream.h" +#include "SoftwareRenderer.h" /**************** Previews ****************/ class PreviewRenderLandscape : public BasePreview @@ -182,7 +183,7 @@ void FormRender::startQuickRender() { rendererDelete(_renderer); } - _renderer = sceneryCreateStandardRenderer(); + _renderer = new SoftwareRenderer(); _renderer_inited = true; DialogRender* dialog = new DialogRender(this, _renderer); @@ -198,7 +199,7 @@ void FormRender::startRender() { rendererDelete(_renderer); } - _renderer = sceneryCreateStandardRenderer(); + _renderer = new SoftwareRenderer(); _renderer_inited = true; DialogRender* dialog = new DialogRender(this, _renderer); diff --git a/src/paysages.pro b/src/paysages.pro index 0b6e3d4..d43028b 100644 --- a/src/paysages.pro +++ b/src/paysages.pro @@ -6,6 +6,7 @@ SUBDIRS = \ basics \ definition \ rendering \ + render/software \ render/opengl \ editing \ controlling \ diff --git a/src/render/opengl/opengl.pro b/src/render/opengl/opengl.pro index 5557b2d..59896d6 100644 --- a/src/render/opengl/opengl.pro +++ b/src/render/opengl/opengl.pro @@ -11,6 +11,8 @@ TEMPLATE = lib DEFINES += OPENGL_LIBRARY +include(../../common.pri) + SOURCES += \ OpenGLRenderer.cpp \ BaseExplorerChunk.cpp \ diff --git a/src/render/software/FluidMediumInterface.cpp b/src/render/software/FluidMediumInterface.cpp new file mode 100644 index 0000000..aa68a53 --- /dev/null +++ b/src/render/software/FluidMediumInterface.cpp @@ -0,0 +1 @@ +#include "FluidMediumInterface.h" diff --git a/src/render/software/FluidMediumInterface.h b/src/render/software/FluidMediumInterface.h new file mode 100644 index 0000000..f706080 --- /dev/null +++ b/src/render/software/FluidMediumInterface.h @@ -0,0 +1,25 @@ +#ifndef FLUIDMEDIUMINTERFACE_H +#define FLUIDMEDIUMINTERFACE_H + +#include "software_global.h" + +namespace paysages { +namespace software { + +/*! + * \brief Interface to a fluid medium compatible class. + */ +class SOFTWARESHARED_EXPORT FluidMediumInterface +{ +public: + /*! + * Return true if the object may change the fluid medium on the given segment. + * When returning true, the object may alter 'segment' to limit its influence. + */ + virtual bool checkInfluence(SpaceSegment& segment) const = 0; +}; + +} +} + +#endif // FLUIDMEDIUMINTERFACE_H diff --git a/src/render/software/FluidMediumManager.cpp b/src/render/software/FluidMediumManager.cpp new file mode 100644 index 0000000..9f66e75 --- /dev/null +++ b/src/render/software/FluidMediumManager.cpp @@ -0,0 +1,51 @@ +#include "FluidMediumManager.h" + +#include "SoftwareRenderer.h" +#include "FluidMediumInterface.h" + +FluidMediumManager::FluidMediumManager(SoftwareRenderer* renderer): + renderer(renderer) +{ +} + +FluidMediumManager::~FluidMediumManager() +{ +} + +void FluidMediumManager::clearMedia() +{ + media.clear(); +} + +void FluidMediumManager::registerMedium(FluidMediumInterface *medium) +{ + media.push_back(medium); +} + +Color FluidMediumManager::applyTraversal(const Vector3 &eye, const Vector3 &location, const Color &color) const +{ + // Collect potential segments + SpaceSegment ray(eye, location); + int max_segments = media.size(); + FluidMediumSegment* segments; + segments = new FluidMediumSegment[max_segments]; + int segment_count = getTraversedMedia(segments, ray, max_segments); + + delete[] segments; + return color; +} + +int FluidMediumManager::getTraversedMedia(FluidMediumSegment segments[], const SpaceSegment &ray, int max_segments) const +{ + int added = 0; + for (auto &medium : media) + { + SpaceSegment ray_inter(ray); + if (added < max_segments and medium->checkInfluence(ray_inter)) + { + // The medium intersect with the ray + segments[added++] = {medium, ray_inter}; + } + } + return added; +} diff --git a/src/render/software/FluidMediumManager.h b/src/render/software/FluidMediumManager.h new file mode 100644 index 0000000..552275c --- /dev/null +++ b/src/render/software/FluidMediumManager.h @@ -0,0 +1,62 @@ +#ifndef FLUIDMEDIUMMANAGER_H +#define FLUIDMEDIUMMANAGER_H + +#include "software_global.h" + +#include "SpaceSegment.h" +#include "tools/color.h" + +namespace paysages { +namespace software { + +typedef struct { + FluidMediumInterface* medium; + SpaceSegment segment; +} FluidMediumSegment; + +/*! + * \brief Global object to interact with fluid medium (air, water, clouds...) + * + * This object handles the traversal of fluid medium and the collecting of + * medium density and properties. + * It is mainly used to compute the alteration made by such media on light. + */ +class SOFTWARESHARED_EXPORT FluidMediumManager +{ +public: + FluidMediumManager(SoftwareRenderer *renderer); + virtual ~FluidMediumManager(); + + /*! + * \brief Remove all registered medium. + */ + void clearMedia(); + + /*! + * \brief Register a new medium in the manager. + */ + void registerMedium(FluidMediumInterface *medium); + + /*! + * \brief Apply complete medium traversal + * \param eye Position of the camera + * \param location Point we look at + * \param color Light initially received from 'location' + * \return Light received by 'eye', transformed by medium traversal + */ + virtual Color applyTraversal(const Vector3 &eye, const Vector3 &location, const Color &color) const; + + /*! + * \brief Get the potential media traversed by a ray, unsorted + */ + virtual int getTraversedMedia(FluidMediumSegment segments[], const SpaceSegment &ray, int max_segments) const; + +private: + SoftwareRenderer *renderer; + std::vector media; +}; + +} +} + +#endif // FLUIDMEDIUMTRAVERSAL_H diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp new file mode 100644 index 0000000..bdc375a --- /dev/null +++ b/src/render/software/SoftwareRenderer.cpp @@ -0,0 +1,36 @@ +#include "SoftwareRenderer.h" + +#include "camera.h" +#include "Scenery.h" +#include "FluidMediumManager.h" + +SoftwareRenderer::SoftwareRenderer(Scenery* scenery) +{ + fluid_medium = new FluidMediumManager(this); + + if (scenery) + { + this->scenery = scenery; + } + else + { + this->scenery = Scenery::getCurrent(); + } + this->scenery->bindToRenderer(this); +} + +SoftwareRenderer::~SoftwareRenderer() +{ + delete fluid_medium; +} + +void SoftwareRenderer::initialize() +{ + //fluid_medium->registerMedium(water_renderer); +} + +/*Color SoftwareRenderer::applyMediumTraversal(Vector3 location, Color color) +{ + Vector3 eye = cameraGetLocation(scenery->getCamera()); + return fluid_medium->applyTraversal(eye, location, color); +}*/ diff --git a/src/render/software/SoftwareRenderer.h b/src/render/software/SoftwareRenderer.h new file mode 100644 index 0000000..09a1ee7 --- /dev/null +++ b/src/render/software/SoftwareRenderer.h @@ -0,0 +1,38 @@ +#ifndef SOFTWARERENDERER_H +#define SOFTWARERENDERER_H + +#include "software_global.h" + +#include "renderer.h" + +class Scenery; + +namespace paysages { +namespace software { + +/*! + * \brief This class renders a defined scenery in sotware mode (using only standard CPU computations). + */ +class SOFTWARESHARED_EXPORT SoftwareRenderer: public Renderer +{ + +public: + SoftwareRenderer(Scenery* scenery=0); + virtual ~SoftwareRenderer(); + + virtual void initialize(); + + inline Scenery* getScenery() const {return scenery;} + inline FluidMediumManager* getFluidMediumManager() const {return fluid_medium;} + + //virtual Color applyMediumTraversal(Vector3 location, Color color) override; + +private: + Scenery* scenery; + FluidMediumManager* fluid_medium; +}; + +} +} + +#endif // SOFTWARERENDERER_H diff --git a/src/render/software/software.pro b/src/render/software/software.pro new file mode 100644 index 0000000..a7c0148 --- /dev/null +++ b/src/render/software/software.pro @@ -0,0 +1,56 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2013-11-09T15:13:23 +# +#------------------------------------------------- + +QT -= gui + +TARGET = paysages_render_software +TEMPLATE = lib + +DEFINES += SOFTWARE_LIBRARY + +include(../../common.pri) + +SOURCES += SoftwareRenderer.cpp \ + FluidMediumInterface.cpp \ + FluidMediumManager.cpp + +HEADERS += SoftwareRenderer.h\ + software_global.h \ + FluidMediumInterface.h \ + FluidMediumManager.h + +unix:!symbian { + maemo5 { + target.path = /opt/usr/lib + } else { + target.path = /usr/lib + } + INSTALLS += target +} + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../system/release/ -lpaysages_system +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../system/debug/ -lpaysages_system +else:unix: LIBS += -L$$OUT_PWD/../../system/ -lpaysages_system +INCLUDEPATH += $$PWD/../../system +DEPENDPATH += $$PWD/../../system + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../basics/release/ -lpaysages_basics +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../basics/debug/ -lpaysages_basics +else:unix: LIBS += -L$$OUT_PWD/../../basics/ -lpaysages_basics +INCLUDEPATH += $$PWD/../../basics +DEPENDPATH += $$PWD/../../basics + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../definition/release/ -lpaysages_definition +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../definition/debug/ -lpaysages_definition +else:unix: LIBS += -L$$OUT_PWD/../../definition/ -lpaysages_definition +INCLUDEPATH += $$PWD/../../definition +DEPENDPATH += $$PWD/../../definition + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../rendering/release/ -lpaysages_rendering +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../rendering/debug/ -lpaysages_rendering +else:unix: LIBS += -L$$OUT_PWD/../../rendering/ -lpaysages_rendering +INCLUDEPATH += $$PWD/../../rendering +DEPENDPATH += $$PWD/../../rendering diff --git a/src/render/software/software_global.h b/src/render/software/software_global.h new file mode 100644 index 0000000..59a1fb7 --- /dev/null +++ b/src/render/software/software_global.h @@ -0,0 +1,25 @@ +#ifndef SOFTWARE_GLOBAL_H +#define SOFTWARE_GLOBAL_H + +#include + +#if defined(SOFTWARE_LIBRARY) +# define SOFTWARESHARED_EXPORT Q_DECL_EXPORT +#else +# define SOFTWARESHARED_EXPORT Q_DECL_IMPORT +#endif + +#include "basics_global.h" + +namespace paysages { +namespace software { + class SoftwareRenderer; + class FluidMediumManager; + class FluidMediumInterface; + class FluidMediumCollector; +} +} + +using namespace paysages::software; + +#endif // SOFTWARE_GLOBAL_H diff --git a/src/rendering/Scenery.cpp b/src/rendering/Scenery.cpp index c8fde98..e0a71f0 100644 --- a/src/rendering/Scenery.cpp +++ b/src/rendering/Scenery.cpp @@ -39,6 +39,11 @@ Scenery::~Scenery() WaterDefinitionClass.destroy(water); } +Scenery* Scenery::getCurrent() +{ + return _main_scenery; +} + void Scenery::save(PackStream* stream) { BaseDefinition::save(stream); diff --git a/src/rendering/Scenery.h b/src/rendering/Scenery.h index 64a63c1..5cdad94 100644 --- a/src/rendering/Scenery.h +++ b/src/rendering/Scenery.h @@ -30,6 +30,8 @@ public: Scenery(); virtual ~Scenery(); + static Scenery* getCurrent(); + virtual void save(PackStream* stream); virtual void load(PackStream* stream); diff --git a/src/rendering/atmosphere/atm_preview.cpp b/src/rendering/atmosphere/atm_preview.cpp index bfdb93e..ec1498b 100644 --- a/src/rendering/atmosphere/atm_preview.cpp +++ b/src/rendering/atmosphere/atm_preview.cpp @@ -51,7 +51,7 @@ static Mount MOUNTS[MOUNTS_COUNT] = { }; static SurfaceMaterial MOUNT_MATERIAL = { - {0.4, 0.4, 0.4, 1.0}, 0.0, 0.0 + {0.4, 0.4, 0.4, 1.0}, 0.0, 0.0, 0.0, 0.0, {0.0, 0.0, 0.0, 0.0} }; static inline int _rayIntersectsTriangle(Vector3 p, Vector3 d, Vector3 v0, Vector3 v1, Vector3 v2, Vector3* hit) diff --git a/src/rendering/camera.cpp b/src/rendering/camera.cpp index 65dab66..8c9a5af 100644 --- a/src/rendering/camera.cpp +++ b/src/rendering/camera.cpp @@ -11,8 +11,9 @@ #include "rendering/terrain/public.h" #include "rendering/water/public.h" -struct CameraDefinition +class CameraDefinition { +public: /* Definition */ Vector3 location; VectorSpherical direction; @@ -207,7 +208,7 @@ void cameraSetLocation(CameraDefinition* camera, Vector3 location) void cameraSetLocationCoords(CameraDefinition* camera, double x, double y, double z) { - Vector3 v = {x, y, z}; + Vector3 v(x, y, z); cameraSetLocation(camera, v); } @@ -228,7 +229,7 @@ void cameraSetTarget(CameraDefinition* camera, Vector3 target) void cameraSetTargetCoords(CameraDefinition* camera, double x, double y, double z) { - Vector3 v = {x, y, z}; + Vector3 v(x, y, z); cameraSetTarget(camera, v); } diff --git a/src/rendering/camera.h b/src/rendering/camera.h index 16826ea..1828e98 100644 --- a/src/rendering/camera.h +++ b/src/rendering/camera.h @@ -9,7 +9,7 @@ namespace paysages { namespace system {class PackStream;} } -typedef struct CameraDefinition CameraDefinition; +class CameraDefinition; typedef struct { diff --git a/src/rendering/render.cpp b/src/rendering/render.cpp index f40659e..1ad7316 100644 --- a/src/rendering/render.cpp +++ b/src/rendering/render.cpp @@ -10,6 +10,7 @@ #include "Thread.h" #include "Mutex.h" #include "System.h" +#include "Vector3.h" typedef struct { @@ -21,7 +22,11 @@ typedef struct } flags; union { - Vector3 location; + struct { + double x; + double y; + double z; + } location; struct { double r; double g; @@ -343,7 +348,9 @@ static void _pushFragment(RenderArea* area, int x, int y, double z, int edge, Ve pixel_data->flags.dirty = (unsigned char)1; pixel_data->flags.edge = (unsigned char)edge; pixel_data->flags.callback = (unsigned char)callback; - pixel_data->data.location = location; + pixel_data->data.location.x = location.x; + pixel_data->data.location.y = location.y; + pixel_data->data.location.z = location.z; pixel_data->z = z; _setDirtyPixel(area, x, y); } @@ -617,7 +624,8 @@ void* _renderPostProcessChunk(void* data) callback = chunk->area->fragment_callbacks[fragment->flags.callback]; if (callback.function) { - col = callback.function(chunk->area->renderer, fragment->data.location, callback.data); + Vector3 location(fragment->data.location.x, fragment->data.location.y, fragment->data.location.z); + col = callback.function(chunk->area->renderer, location, callback.data); /*colorNormalize(&col);*/ } else diff --git a/src/rendering/render.h b/src/rendering/render.h index 5a788ad..fe6b85e 100644 --- a/src/rendering/render.h +++ b/src/rendering/render.h @@ -6,7 +6,7 @@ #include "tools/color.h" #include "tools/euclid.h" -typedef Color (*f_RenderFragmentCallback)(struct Renderer* renderer, Vector3 location, void* data); +typedef Color (*f_RenderFragmentCallback)(Renderer* renderer, Vector3 location, void* data); typedef void (*RenderCallbackStart)(int width, int height, Color background); typedef void (*RenderCallbackDraw)(int x, int y, Color col); diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 3c8e1a6..bce527b 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -13,7 +13,7 @@ #include "rendering/textures/public.h" #include "rendering/water/public.h" -static RayCastingResult _RAYCASTING_NULL = {0}; +static RayCastingResult _RAYCASTING_NULL = {0, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static void* _renderFirstPass(void* data) { @@ -117,69 +117,89 @@ static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vecto return result; } -static Color _applyMediumTraversal(Renderer* renderer, Vector3 location, Color color) + + + + + +Renderer::Renderer() { - color = renderer->atmosphere->applyAerialPerspective(renderer, location, color).final; - color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location); + RenderParams params = {1, 1, 1, 5}; + + render_quality = 5; + render_width = 1; + render_height = 1; + render_interrupt = 0; + render_progress = 0.0; + is_rendering = 0; + render_camera = cameraCreateDefinition(); + render_area = renderCreateArea(this); + + renderSetParams(render_area, params); + + addRenderProgress = _addRenderProgress; + getCameraLocation = _getCameraLocation; + getCameraDirection = _getCameraDirection; + getPrecision = _getPrecision; + projectPoint = _projectPoint; + unprojectPoint = _unprojectPoint; + pushTriangle = _pushTriangle; + pushQuad = _pushQuad; + pushDisplacedTriangle = _pushDisplacedTriangle; + pushDisplacedQuad = _pushDisplacedQuad; + + rayWalking = _rayWalking; + + applyLightingToSurface = _applyLightingToSurface; + + lighting = lightingManagerCreate(); + + atmosphere = (AtmosphereRenderer*)AtmosphereRendererClass.create(); + clouds = (CloudsRenderer*)CloudsRendererClass.create(); + terrain = (TerrainRenderer*)TerrainRendererClass.create(); + textures = (TexturesRenderer*)TexturesRendererClass.create(); + water = (WaterRenderer*)WaterRendererClass.create(); +} + +Renderer::~Renderer() +{ + cameraDeleteDefinition(render_camera); + lightingManagerDelete(lighting); + + AtmosphereRendererClass.destroy(atmosphere); + CloudsRendererClass.destroy(clouds); + TerrainRendererClass.destroy(terrain); + TexturesRendererClass.destroy(textures); + WaterRendererClass.destroy(water); + + renderDeleteArea(render_area); +} + +Color Renderer::applyMediumTraversal(Vector3 location, Color color) +{ + color = atmosphere->applyAerialPerspective(this, location, color).final; + color = clouds->getColor(this, color, getCameraLocation(this, location), location); return color; } + + + + + + + + + +// Old API compat + Renderer* rendererCreate() { - Renderer* result = new Renderer; - RenderParams params = {1, 1, 1, 5}; - - result->render_quality = 5; - result->render_width = 1; - result->render_height = 1; - result->render_interrupt = 0; - result->render_progress = 0.0; - result->is_rendering = 0; - result->render_camera = cameraCreateDefinition(); - result->render_area = renderCreateArea(result); - - renderSetParams(result->render_area, params); - - result->addRenderProgress = _addRenderProgress; - result->getCameraLocation = _getCameraLocation; - result->getCameraDirection = _getCameraDirection; - result->getPrecision = _getPrecision; - result->projectPoint = _projectPoint; - result->unprojectPoint = _unprojectPoint; - result->pushTriangle = _pushTriangle; - result->pushQuad = _pushQuad; - result->pushDisplacedTriangle = _pushDisplacedTriangle; - result->pushDisplacedQuad = _pushDisplacedQuad; - - result->rayWalking = _rayWalking; - - result->applyLightingToSurface = _applyLightingToSurface; - result->applyMediumTraversal = _applyMediumTraversal; - - result->lighting = lightingManagerCreate(); - - result->atmosphere = (AtmosphereRenderer*)AtmosphereRendererClass.create(); - result->clouds = (CloudsRenderer*)CloudsRendererClass.create(); - result->terrain = (TerrainRenderer*)TerrainRendererClass.create(); - result->textures = (TexturesRenderer*)TexturesRendererClass.create(); - result->water = (WaterRenderer*)WaterRendererClass.create(); - - return result; + return new Renderer(); } void rendererDelete(Renderer* renderer) { - cameraDeleteDefinition(renderer->render_camera); - lightingManagerDelete(renderer->lighting); - - AtmosphereRendererClass.destroy(renderer->atmosphere); - CloudsRendererClass.destroy(renderer->clouds); - TerrainRendererClass.destroy(renderer->terrain); - TexturesRendererClass.destroy(renderer->textures); - WaterRendererClass.destroy(renderer->water); - - renderDeleteArea(renderer->render_area); - delete renderer; } diff --git a/src/rendering/renderer.h b/src/rendering/renderer.h index 71e4df3..512e6a9 100644 --- a/src/rendering/renderer.h +++ b/src/rendering/renderer.h @@ -14,8 +14,12 @@ class TexturesRenderer; class CloudsRenderer; class WaterRenderer; -struct Renderer +class Renderer { +public: + Renderer(); + virtual ~Renderer(); + /* Render base configuration */ int render_quality; int render_width; @@ -40,7 +44,7 @@ struct Renderer /* Shortcuts */ Color(*applyLightingToSurface)(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material); - Color(*applyMediumTraversal)(Renderer* renderer, Vector3 location, Color color); + virtual Color applyMediumTraversal(Vector3 location, Color color); /* Scenery related */ RayCastingResult(*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds); diff --git a/src/rendering/rendering.pro b/src/rendering/rendering.pro index 7059479..e9e7343 100644 --- a/src/rendering/rendering.pro +++ b/src/rendering/rendering.pro @@ -5,7 +5,8 @@ TEMPLATE = lib TARGET = paysages_rendering DEFINES += RENDERING_LIBRARY -CONFIG(release, debug|release): DEFINES += NDEBUG + +include(../common.pri) INCLUDEPATH += $$PWD/.. diff --git a/src/rendering/shared/types.h b/src/rendering/shared/types.h index f7bcc09..f6dc18f 100644 --- a/src/rendering/shared/types.h +++ b/src/rendering/shared/types.h @@ -4,7 +4,7 @@ #include "../tools/euclid.h" #include "../tools/color.h" -typedef struct Renderer Renderer; +class Renderer; typedef struct { diff --git a/src/rendering/terrain/ter_render.cpp b/src/rendering/terrain/ter_render.cpp index c8b036b..e86d278 100644 --- a/src/rendering/terrain/ter_render.cpp +++ b/src/rendering/terrain/ter_render.cpp @@ -144,11 +144,11 @@ static Color _fakeGetFinalColor(Renderer* renderer, Vector3 location, double pre return COLOR_GREEN; } -static Color _realGetFinalColor(Renderer* renderer, Vector3 location, double precision) +static Color _realGetFinalColor(Renderer* renderer, Vector3 location, double) { /* TODO Restore precision control */ TexturesResult textures = renderer->textures->applyToTerrain(renderer, location.x, location.z); - return renderer->applyMediumTraversal(renderer, textures.final_location, textures.final_color); + return renderer->applyMediumTraversal(textures.final_location, textures.final_color); } static RayCastingResult _fakeCastRay(Renderer* renderer, Vector3 start, Vector3 direction) diff --git a/src/rendering/tools/array.cpp b/src/rendering/tools/array.cpp index b52e65f..4e66439 100644 --- a/src/rendering/tools/array.cpp +++ b/src/rendering/tools/array.cpp @@ -6,16 +6,18 @@ void* naiveArrayInsert(void** array, size_t item_size, int item_count, int location) { + char** barray = (char**)array; + assert(location >= 0); assert(location <= item_count); - *array = realloc(*array, item_size * (item_count + 1)); + *barray = (char*)realloc(*barray, item_size * (item_count + 1)); if (location < item_count) { - memmove(*array + item_size * (location + 1), *array + item_size * location, item_size * (item_count - location)); + memmove(*barray + item_size * (location + 1), *barray + item_size * location, item_size * (item_count - location)); } - return *array + item_size * location; + return *barray + item_size * location; } void arrayCreate(Array* array, int item_size) @@ -35,7 +37,7 @@ void arrayDelete(Array* array) void* arrayAppend(Array* array, void* item) { - void* dest; + char* dest; size_t item_size = (size_t)array->item_size; if (array->length >= array->alloc_length) @@ -44,7 +46,7 @@ void* arrayAppend(Array* array, void* item) array->data = realloc(array->data, item_size * array->alloc_length); } - dest = array->data + item_size * array->length; + dest = ((char*)array->data) + item_size * array->length; memcpy(dest, item, item_size); array->length++; @@ -56,7 +58,7 @@ void* arrayAppend(Array* array, void* item) void arrayInsert(Array* array, void* item, int position) { size_t item_size; - void* dest; + char* dest; if (position >= array->length) { @@ -72,9 +74,9 @@ void arrayInsert(Array* array, void* item, int position) array->data = realloc(array->data, item_size * array->alloc_length); } - dest = array->data + item_size * position; + dest = ((char*)array->data) + item_size * position; memmove(dest + item_size, dest, array->length - position); - memcpy(array->data + item_size * position, item, item_size); + memcpy(((char*)array->data) + item_size * position, item, item_size); array->length++; array->dirty = 1; @@ -88,7 +90,7 @@ void arrayReplace(Array* array, void* item, int position) if (position >= 0 && position < array->length) { item_size = (size_t)array->item_size; - memcpy(array->data + item_size * position, item, item_size); + memcpy(((char*)array->data) + item_size * position, item, item_size); array->dirty = 1; } @@ -105,7 +107,7 @@ void arrayLStrip(Array* array, int count) else if (count >= 0) { item_size = (size_t)array->item_size; - memmove(array->data, array->data + item_size * count, item_size * (array->length - count)); + memmove(array->data, ((char*)array->data) + item_size * count, item_size * (array->length - count)); array->length -= count; array->dirty = 1; } diff --git a/src/rendering/tools/color.cpp b/src/rendering/tools/color.cpp index 9d82d62..eaa2cca 100644 --- a/src/rendering/tools/color.cpp +++ b/src/rendering/tools/color.cpp @@ -212,8 +212,9 @@ void colorLimitPower(Color* col, double max_power) } /******************************** ColorProfile ********************************/ -struct ColorProfile +class ColorProfile { +public: double minvalue; double maxvalue; Color(*mapper)(Color col, double exposure); @@ -297,12 +298,12 @@ void colorProfileSetToneMapping(ColorProfile* profile, ToneMappingOperator tonem profile->exposure = exposure; } -void colorProfileSave(PackStream* stream, ColorProfile* profile) +void colorProfileSave(PackStream*, ColorProfile*) { /* TODO */ } -void colorProfileLoad(PackStream* stream, ColorProfile* profile) +void colorProfileLoad(PackStream*, ColorProfile*) { /* TODO */ } diff --git a/src/rendering/tools/color.h b/src/rendering/tools/color.h index cc8ca80..ed4b15f 100644 --- a/src/rendering/tools/color.h +++ b/src/rendering/tools/color.h @@ -48,7 +48,7 @@ RENDERINGSHARED_EXPORT double colorGetPower(Color* col); RENDERINGSHARED_EXPORT void colorLimitPower(Color* col, double max_power); /* HDR profile for tone-mapping */ -typedef struct ColorProfile ColorProfile; +class ColorProfile; typedef enum { TONE_MAPPING_UNCHARTED, diff --git a/src/rendering/tools/euclid.cpp b/src/rendering/tools/euclid.cpp index 5ed1b08..0bb1a8b 100644 --- a/src/rendering/tools/euclid.cpp +++ b/src/rendering/tools/euclid.cpp @@ -1,129 +1,8 @@ #include "euclid.h" #include -#include "../tools.h" #include "PackStream.h" -Vector3 VECTOR_ZERO = {0.0, 0.0, 0.0}; -Vector3 VECTOR_DOWN = {0.0, -1.0, 0.0}; -Vector3 VECTOR_UP = {0.0, 1.0, 0.0}; -Vector3 VECTOR_NORTH = {0.0, 0.0, -1.0}; -Vector3 VECTOR_SOUTH = {0.0, 0.0, 1.0}; -Vector3 VECTOR_WEST = {-1.0, 0.0, 0.0}; -Vector3 VECTOR_EAST = {1.0, 0.0, 0.0}; - -void v3Save(PackStream* stream, Vector3* v) -{ - stream->write(&v->x); - stream->write(&v->y); - stream->write(&v->z); -} - -void v3Load(PackStream* stream, Vector3* v) -{ - stream->read(&v->x); - stream->read(&v->y); - stream->read(&v->z); -} - -Vector3 v3Translate(Vector3 v1, double x, double y, double z) -{ - Vector3 result; - result.x = v1.x + x; - result.y = v1.y + y; - result.z = v1.z + z; - return result; -} - -Vector3 v3Add(Vector3 v1, Vector3 v2) -{ - Vector3 result; - result.x = v1.x + v2.x; - result.y = v1.y + v2.y; - result.z = v1.z + v2.z; - return result; -} - -Vector3 v3Sub(Vector3 v1, Vector3 v2) -{ - Vector3 result; - result.x = v1.x - v2.x; - result.y = v1.y - v2.y; - result.z = v1.z - v2.z; - return result; -} - -Vector3 v3Neg(Vector3 v) -{ - Vector3 result; - result.x = -v.x; - result.y = -v.y; - result.z = -v.z; - return result; -} - -Vector3 v3Scale(Vector3 v, double scale) -{ - Vector3 result; - result.x = v.x * scale; - result.y = v.y * scale; - result.z = v.z * scale; - return result; -} - -double v3Norm(Vector3 v) -{ - return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); -} - -Vector3 v3Normalize(Vector3 v) -{ - double norm = v3Norm(v); - if (norm == 0.0) - { - return VECTOR_ZERO; - } - else - { - return v3Scale(v, 1.0 / norm); - } -} - -double v3Dot(Vector3 v1, Vector3 v2) -{ - return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; -} - -Vector3 v3Cross(Vector3 v1, Vector3 v2) -{ - Vector3 result; - result.x = v1.y * v2.z - v1.z * v2.y; - result.y = v1.z * v2.x - v1.x * v2.z; - result.z = v1.x * v2.y - v1.y * v2.x; - return result; -} - -VectorSpherical v3ToSpherical(Vector3 v) -{ - VectorSpherical result; - - result.phi = euclidGet2DAngle(v.x, -v.z); - result.theta = euclidGet2DAngle(sqrt(v.x * v.x + v.z * v.z), v.y); - if (v.y < 0.0) - { - result.theta -= 2.0 * M_PI; - } - result.r = v3Norm(v); - - return result; -} - -Vector3 v3FromSpherical(VectorSpherical v) -{ - Vector3 result = {v.r * cos(v.phi) * cos(v.theta), v.r * sin(v.theta), -v.r * sin(v.phi) * cos(v.theta)}; - return result; -} - void m4Save(PackStream* stream, Matrix4* m) { stream->write(&m->a); diff --git a/src/rendering/tools/euclid.h b/src/rendering/tools/euclid.h index febdcb7..d9cae41 100644 --- a/src/rendering/tools/euclid.h +++ b/src/rendering/tools/euclid.h @@ -3,51 +3,13 @@ #include "../rendering_global.h" +// TEMP +#include "Vector3.h" + namespace paysages { namespace system {class PackStream;} } -/* - * Cartesian coordinates (X, Y, Z) - right handed : - * - * Y (up) - * | - * | - * +----X - * / - * / - * Z - * - * Spherical coordinates (R, PHI, THETA) : - * - * R is the distance to origin - * PHI is typical azimuth - * THETA is elevation angle (not polar angle!) - * - * X=1 Y=0 Z=0 => PHI=0 - * X=0 Y=0 Z=-1 => PHI=PI/2 - * X=-1 Y=0 Z=0 => PHI=PI - * X=0 Y=0 Z=1 => PHI=3*PI/2 - * - * X=1 Y=0 Z=0 => THETA=0 - * X=0 Y=1 Z=0 => THETA=PI/2 - * X=0 Y=-1 Z=0 => THETA=-PI/2 - */ - -typedef struct -{ - double x; - double y; - double z; -} Vector3; - -typedef struct -{ - double r; - double theta; - double phi; -} VectorSpherical; - typedef struct { double a; @@ -68,33 +30,6 @@ typedef struct double p; } Matrix4; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_ZERO; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_DOWN; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_UP; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_NORTH; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_SOUTH; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_EAST; -RENDERINGSHARED_EXPORT extern Vector3 VECTOR_WEST; - -static inline Vector3 v3(double x, double y, double z) -{ - Vector3 result = {x, y, z}; - return result; -}; -RENDERINGSHARED_EXPORT void v3Save(PackStream* stream, Vector3* v); -RENDERINGSHARED_EXPORT void v3Load(PackStream* stream, Vector3* v); -RENDERINGSHARED_EXPORT Vector3 v3Translate(Vector3 v1, double x, double y, double z); -RENDERINGSHARED_EXPORT Vector3 v3Add(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT Vector3 v3Sub(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT Vector3 v3Neg(Vector3 v); -RENDERINGSHARED_EXPORT Vector3 v3Scale(Vector3 v, double scale); -RENDERINGSHARED_EXPORT double v3Norm(Vector3 v); -RENDERINGSHARED_EXPORT Vector3 v3Normalize(Vector3 v); -RENDERINGSHARED_EXPORT double v3Dot(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT Vector3 v3Cross(Vector3 v1, Vector3 v2); -RENDERINGSHARED_EXPORT VectorSpherical v3ToSpherical(Vector3 v); -RENDERINGSHARED_EXPORT Vector3 v3FromSpherical(VectorSpherical v); - RENDERINGSHARED_EXPORT void m4Save(PackStream* stream, Matrix4* m); RENDERINGSHARED_EXPORT void m4Load(PackStream* stream, Matrix4* m); RENDERINGSHARED_EXPORT Matrix4 m4NewIdentity(); diff --git a/src/rendering/tools/lighting.cpp b/src/rendering/tools/lighting.cpp index fb12ffb..4ecc5dd 100644 --- a/src/rendering/tools/lighting.cpp +++ b/src/rendering/tools/lighting.cpp @@ -15,8 +15,9 @@ typedef struct void* data; } LightFilterCallback; -struct LightingManager +class LightingManager { +public: int specularity_enabled; int callbacks_count; LightFilterCallback callbacks[MAX_CALLBACK_COUNT]; diff --git a/src/rendering/tools/lighting.h b/src/rendering/tools/lighting.h index e3992f4..06a6657 100644 --- a/src/rendering/tools/lighting.h +++ b/src/rendering/tools/lighting.h @@ -33,7 +33,7 @@ typedef struct typedef int (*FuncLightingAlterLight)(void* data, LightDefinition* light, Vector3 at); -typedef struct LightingManager LightingManager; +class LightingManager; typedef struct LightStatus LightStatus; RENDERINGSHARED_EXPORT LightingManager* lightingManagerCreate(); diff --git a/src/rendering/tools/memory.cpp b/src/rendering/tools/memory.cpp index 223cad0..02775b6 100644 --- a/src/rendering/tools/memory.cpp +++ b/src/rendering/tools/memory.cpp @@ -3,11 +3,11 @@ #include #include -void* memory2dRealloc(void* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset) +char* memory2dRealloc(char* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset) { int xstart, xend, xlen; int ystart, yend, y; - void* result = malloc(datasize * newxsize * newysize); + char* result = (char*)malloc(datasize * newxsize * newysize); /* Move remaining part*/ ystart = yoffset; diff --git a/src/rendering/tools/memory.h b/src/rendering/tools/memory.h index d5134b9..59475e5 100644 --- a/src/rendering/tools/memory.h +++ b/src/rendering/tools/memory.h @@ -7,6 +7,6 @@ #include "../rendering_global.h" -RENDERINGSHARED_EXPORT void* memory2dRealloc(void* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset); +RENDERINGSHARED_EXPORT char* memory2dRealloc(char* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset); #endif diff --git a/src/rendering/water/wat_render.cpp b/src/rendering/water/wat_render.cpp index 034d5b7..be0af3c 100644 --- a/src/rendering/water/wat_render.cpp +++ b/src/rendering/water/wat_render.cpp @@ -290,7 +290,7 @@ static WaterResult _realGetResult(Renderer* renderer, double x, double z) colorMask(&color, &foam); /* Bring color to the camera */ - color = renderer->applyMediumTraversal(renderer, location, color); + color = renderer->applyMediumTraversal(location, color); result.base = definition->material._rgb; result.final = color; diff --git a/src/system/PackStream.cpp b/src/system/PackStream.cpp index 386598b..051f36c 100644 --- a/src/system/PackStream.cpp +++ b/src/system/PackStream.cpp @@ -37,7 +37,7 @@ bool PackStream::bindToFile(const char* filepath, bool write) return stream != NULL; } -void PackStream::write(int* value) +void PackStream::write(const int*value) { if (stream and value) { @@ -45,7 +45,7 @@ void PackStream::write(int* value) } } -void PackStream::write(double* value) +void PackStream::write(const double *value) { if (stream and value) { @@ -53,7 +53,7 @@ void PackStream::write(double* value) } } -void PackStream::write(char* value, int max_length) +void PackStream::write(const char *value, int max_length) { if (stream and value) { @@ -62,7 +62,7 @@ void PackStream::write(char* value, int max_length) } } -void PackStream::write(QString value) +void PackStream::write(const QString &value) { if (stream) { diff --git a/src/system/PackStream.h b/src/system/PackStream.h index 29f0b06..9c23b80 100644 --- a/src/system/PackStream.h +++ b/src/system/PackStream.h @@ -22,10 +22,10 @@ public: bool bindToFile(const char* filepath, bool write=false); - void write(int* value); - void write(double* value); - void write(char* value, int max_length); - void write(QString value); + void write(const int *value); + void write(const double *value); + void write(const char *value, const int max_length); + void write(const QString &value); void read(int* value); void read(double* value); diff --git a/src/system/system.pro b/src/system/system.pro index a23a575..09a3116 100644 --- a/src/system/system.pro +++ b/src/system/system.pro @@ -10,7 +10,8 @@ TEMPLATE = lib TARGET = paysages_system DEFINES += SYSTEM_LIBRARY -CONFIG(release, debug|release): DEFINES += NDEBUG + +include(../common.pri) SOURCES += \ PictureFile.cpp \ diff --git a/src/system/system_global.h b/src/system/system_global.h index 2814783..93b5c7d 100644 --- a/src/system/system_global.h +++ b/src/system/system_global.h @@ -1,7 +1,8 @@ #ifndef SYSTEM_GLOBAL_H #define SYSTEM_GLOBAL_H -/* Shared object helpers */ +#define PAYSAGES_USE_INLINING 1 + #include #if defined(SYSTEM_LIBRARY) # define SYSTEMSHARED_EXPORT Q_DECL_EXPORT @@ -9,10 +10,10 @@ # define SYSTEMSHARED_EXPORT Q_DECL_IMPORT #endif -/* Namespace using */ -namespace paysages -{ - namespace system {} +namespace paysages { +namespace system { + class PackStream; +} } using namespace paysages::system; diff --git a/src/tests/FluidMediumManager_Test.cpp b/src/tests/FluidMediumManager_Test.cpp new file mode 100644 index 0000000..53ba9d6 --- /dev/null +++ b/src/tests/FluidMediumManager_Test.cpp @@ -0,0 +1,110 @@ +#include "BaseTestCase.h" + +#include "SpaceSegment.h" +#include "Scenery.h" +#include "SoftwareRenderer.h" +#include "FluidMediumManager.h" +#include "FluidMediumInterface.h" + +class FluidMediumManager_Test:public BaseTestCase +{ +protected: + virtual void setUp() + { + scenery = new Scenery(); + renderer = new SoftwareRenderer(scenery); + } + + virtual void tearDown() + { + delete renderer; + delete scenery; + } + + Scenery* scenery; + SoftwareRenderer* renderer; +}; + + +TEST_F(FluidMediumManager_Test, getTraversedMedia) +{ + FluidMediumManager manager(renderer); + int traversed; + FluidMediumSegment segments[10]; + class FakeMedium:public FluidMediumInterface + { + public: + void setCut(double ymin, double ymax) + { + this->ymin = ymin; + this->ymax = ymax; + } + + virtual bool checkInfluence(SpaceSegment& segment) const override + { + return segment.intersectYInterval(this->ymin, this->ymax); + } + private: + double ymin = -2.0; + double ymax = -1.0; + }; + SpaceSegment ray(Vector3(0.0, 0.0, 0.0), Vector3(8.0, 10.0, -4.0)); + + // Empty manager + traversed = manager.getTraversedMedia(segments, ray, 10); + ASSERT_EQ(0, traversed); + + // Testing with 1 medium outside the range + FakeMedium m1; + manager.registerMedium(&m1); + traversed = manager.getTraversedMedia(segments, ray, 10); + ASSERT_EQ(0, traversed); + + // Setting the medium in range + m1.setCut(1.0, 2.0); + traversed = manager.getTraversedMedia(segments, ray, 10); + ASSERT_EQ(1, traversed); + EXPECT_EQ((FluidMediumInterface*)&m1, segments[0].medium); + EXPECT_VECTOR3_COORDS(segments[0].segment.getStart(), 0.8, 1.0, -0.4); + EXPECT_VECTOR3_COORDS(segments[0].segment.getEnd(), 1.6, 2.0, -0.8); + + // Testing with 2 media + FakeMedium m2; + m2.setCut(4.0, 12.0); + manager.registerMedium(&m2); + traversed = manager.getTraversedMedia(segments, ray, 10); + ASSERT_EQ(2, traversed); + EXPECT_EQ((FluidMediumInterface*)&m1, segments[0].medium); + EXPECT_VECTOR3_COORDS(segments[0].segment.getStart(), 0.8, 1.0, -0.4); + EXPECT_VECTOR3_COORDS(segments[0].segment.getEnd(), 1.6, 2.0, -0.8); + EXPECT_EQ((FluidMediumInterface*)&m2, segments[1].medium); + EXPECT_VECTOR3_COORDS(segments[1].segment.getStart(), 3.2, 4.0, -1.6); + EXPECT_VECTOR3_COORDS(segments[1].segment.getEnd(), 8.0, 10.0, -4.0); + + // Testing with overlapping media + FakeMedium m3; + m3.setCut(3.0, 4.5); + manager.registerMedium(&m3); + traversed = manager.getTraversedMedia(segments, ray, 10); + ASSERT_EQ(3, traversed); + EXPECT_EQ((FluidMediumInterface*)&m1, segments[0].medium); + EXPECT_VECTOR3_COORDS(segments[0].segment.getStart(), 0.8, 1.0, -0.4); + EXPECT_VECTOR3_COORDS(segments[0].segment.getEnd(), 1.6, 2.0, -0.8); + EXPECT_EQ((FluidMediumInterface*)&m2, segments[1].medium); + EXPECT_VECTOR3_COORDS(segments[1].segment.getStart(), 3.2, 4.0, -1.6); + EXPECT_VECTOR3_COORDS(segments[1].segment.getEnd(), 8.0, 10.0, -4.0); + EXPECT_EQ((FluidMediumInterface*)&m3, segments[2].medium); + EXPECT_VECTOR3_COORDS(segments[2].segment.getStart(), 2.4, 3.0, -1.2); + EXPECT_VECTOR3_COORDS(segments[2].segment.getEnd(), 3.6, 4.5, -1.8); + + // Testing the segment count limit + traversed = manager.getTraversedMedia(segments, ray, 2); + ASSERT_EQ(2, traversed); + EXPECT_EQ((FluidMediumInterface*)&m1, segments[0].medium); + EXPECT_EQ((FluidMediumInterface*)&m2, segments[1].medium); + + // Testing after clear + manager.clearMedia(); + traversed = manager.getTraversedMedia(segments, ray, 10); + ASSERT_EQ(0, traversed); +} diff --git a/src/tests/PackStream_Test.cpp b/src/tests/PackStream_Test.cpp index 5926b92..d2e7407 100644 --- a/src/tests/PackStream_Test.cpp +++ b/src/tests/PackStream_Test.cpp @@ -8,7 +8,7 @@ TEST(PackStream, All) int i; int data_i; double data_d; - char* data_s; + const char* data_s; char buffer[100]; /* Writing to pack */ diff --git a/src/tests/googletest/googletest.pro b/src/tests/googletest/googletest.pro index 0b221c0..dad7319 100644 --- a/src/tests/googletest/googletest.pro +++ b/src/tests/googletest/googletest.pro @@ -11,7 +11,7 @@ TEMPLATE = lib DEFINES += GOOGLETEST_LIBRARY -#QMAKE_CXXFLAGS += -pthread +QMAKE_CXXFLAGS += -pthread -Wno-missing-field-initializers INCLUDEPATH += . ./include diff --git a/src/tests/tests.pro b/src/tests/tests.pro index c9a2176..16f6c0b 100644 --- a/src/tests/tests.pro +++ b/src/tests/tests.pro @@ -4,6 +4,8 @@ CONFIG -= app_bundle TARGET = paysages-tests +include(../common.pri) + SOURCES += main.cpp \ Layers_Test.cpp \ PackStream_Test.cpp \ @@ -14,7 +16,8 @@ SOURCES += main.cpp \ Euclid_Test.cpp \ Bruneton_Test.cpp \ Camera_Test.cpp \ - Clouds_Test.cpp + Clouds_Test.cpp \ + FluidMediumManager_Test.cpp HEADERS += \ BaseTestCase.h @@ -48,3 +51,9 @@ else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../rendering/debug/ else:unix: LIBS += -L$$OUT_PWD/../rendering/ -lpaysages_rendering INCLUDEPATH += $$PWD/../rendering DEPENDPATH += $$PWD/../rendering + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../render/software/release/ -lpaysages_render_software +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../render/software/debug/ -lpaysages_render_software +else:unix: LIBS += -L$$OUT_PWD/../render/software/ -lpaysages_render_software +INCLUDEPATH += $$PWD/../render/software +DEPENDPATH += $$PWD/../render/software