WIP
This commit is contained in:
parent
ce33390321
commit
fb16682876
21 changed files with 484 additions and 23 deletions
|
@ -32,10 +32,16 @@ class BASICSSHARED_EXPORT Maths {
|
|||
*/
|
||||
static double zeroPoint(double segment_length, double edge0, double edge1);
|
||||
|
||||
static inline bool equals(double v1, double v2, double eps = DOUBLE_EPS) {
|
||||
double d = v1 - v2;
|
||||
return d <= eps and d >= -eps;
|
||||
}
|
||||
|
||||
static constexpr double PI = 3.141592653589793238462643383279;
|
||||
static constexpr double PI_2 = PI / 2.0;
|
||||
static constexpr double PI_4 = PI / 4.0;
|
||||
static constexpr double TWOPI = 2.0 * PI;
|
||||
static constexpr double DOUBLE_EPS = 0.0000000001;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,10 @@ Vector3 Vector3::normalize() const {
|
|||
}
|
||||
}
|
||||
|
||||
bool Vector3::isNormalized() const {
|
||||
return Maths::equals(getNorm(), 1.0);
|
||||
}
|
||||
|
||||
double Vector3::dotProduct(const Vector3 &other) const {
|
||||
return x * other.x + y * other.y + z * other.z;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ class BASICSSHARED_EXPORT Vector3 {
|
|||
Vector3 scale(double scaling) const;
|
||||
double getNorm() const;
|
||||
Vector3 normalize() const;
|
||||
bool isNormalized() const;
|
||||
|
||||
Vector3 add(double x, double y, double z) const;
|
||||
Vector3 add(const Vector3 &other) const;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#include "AtmosphereDefinition.h"
|
||||
#include "CameraDefinition.h"
|
||||
#include "Logs.h"
|
||||
#include "RandomGenerator.h"
|
||||
#include "RenderConfig.h"
|
||||
#include "Scenery.h"
|
||||
#include "SoftwareCanvasRenderer.h"
|
||||
#include "SoftwareRayRenderer.h"
|
||||
#include "TimeManager.h"
|
||||
|
||||
#include <cstring>
|
||||
|
@ -17,7 +19,10 @@ static void displayHelp() {
|
|||
printf(" -h Show this help\n");
|
||||
printf(" -ts Run the render test suite\n");
|
||||
printf(" -f x Saved file to load (str)\n");
|
||||
printf(" -n Number of pictures in the sequence\n");
|
||||
printf(" -r x Random seed to use (int)\n");
|
||||
printf(" -s x First picture in the sequence (int)\n");
|
||||
printf(" -n x Number of pictures in the sequence (int)\n");
|
||||
printf(" -rt Use ray tracing renderer instead of rasterization\n");
|
||||
printf(" -rw x Render width (int)\n");
|
||||
printf(" -rh x Render height (int)\n");
|
||||
printf(" -rq x Render quality (int, 1 to 10)\n");
|
||||
|
@ -37,6 +42,7 @@ int main(int argc, char **argv) {
|
|||
RenderConfig conf_render_params(480, 270, 1, 3);
|
||||
int conf_first_picture = 0;
|
||||
int conf_nb_pictures = 1;
|
||||
long unsigned int conf_seed = 0;
|
||||
double conf_daytime_start = -1.0;
|
||||
double conf_daytime_step = 0.0;
|
||||
double conf_camera_step_x = 0.0;
|
||||
|
@ -46,6 +52,7 @@ int main(int argc, char **argv) {
|
|||
double conf_wind_z = 0.0;
|
||||
int outputcount;
|
||||
char outputpath[500];
|
||||
bool raytracing = false;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
@ -57,10 +64,16 @@ int main(int argc, char **argv) {
|
|||
} else if (strcmp(*argv, "-ts") == 0 || strcmp(*argv, "--testsuite") == 0) {
|
||||
runTestSuite();
|
||||
return 0;
|
||||
} else if (strcmp(*argv, "-rt") == 0 || strcmp(*argv, "--raytracing") == 0) {
|
||||
raytracing = true;
|
||||
} else if (strcmp(*argv, "-f") == 0 || strcmp(*argv, "--file") == 0) {
|
||||
if (argc--) {
|
||||
conf_file_path = *(++argv);
|
||||
}
|
||||
} else if (strcmp(*argv, "-r") == 0 || strcmp(*argv, "--randomseed") == 0) {
|
||||
if (argc--) {
|
||||
conf_seed = atoi(*(++argv));
|
||||
}
|
||||
} else if (strcmp(*argv, "-s") == 0 || strcmp(*argv, "--start") == 0) {
|
||||
if (argc--) {
|
||||
conf_first_picture = atoi(*(++argv));
|
||||
|
@ -120,10 +133,15 @@ int main(int argc, char **argv) {
|
|||
|
||||
printf("Initializing ...\n");
|
||||
Scenery *scenery = new Scenery();
|
||||
RandomGenerator generator(conf_seed);
|
||||
|
||||
if (conf_file_path) {
|
||||
scenery->loadGlobal(conf_file_path);
|
||||
} else {
|
||||
if (conf_seed) {
|
||||
RandomGeneratorDefault = generator;
|
||||
}
|
||||
printf("Using seed %lu\n", RandomGeneratorDefault.getSeed());
|
||||
scenery->autoPreset();
|
||||
}
|
||||
|
||||
|
@ -140,7 +158,7 @@ int main(int argc, char **argv) {
|
|||
Vector3 step = {conf_camera_step_x, conf_camera_step_y, conf_camera_step_z};
|
||||
camera->setLocation(camera->getLocation().add(step));
|
||||
|
||||
renderer = new SoftwareCanvasRenderer(scenery);
|
||||
renderer = raytracing ? new SoftwareRayRenderer(scenery) : new SoftwareCanvasRenderer(scenery);
|
||||
renderer->setConfig(conf_render_params);
|
||||
|
||||
if (outputcount >= conf_first_picture) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "RenderConfig.h"
|
||||
#include "RenderPreviewProvider.h"
|
||||
#include "RenderProgress.h"
|
||||
#include "SoftwareCanvasRenderer.h"
|
||||
#include "SoftwareRayRenderer.h"
|
||||
#include "Thread.h"
|
||||
#include <QQuickItem>
|
||||
#include <QSize>
|
||||
|
@ -99,7 +99,8 @@ void RenderProcess::startRender(Scenery *scenery, const RenderConfig &config) {
|
|||
delete renderer;
|
||||
}
|
||||
|
||||
renderer = new SoftwareCanvasRenderer(scenery);
|
||||
// renderer = new SoftwareCanvasRenderer(scenery);
|
||||
renderer = new SoftwareRayRenderer(scenery);
|
||||
renderer->setConfig(config);
|
||||
|
||||
destination->setCanvas(renderer->getCanvas());
|
||||
|
|
|
@ -1,4 +1,62 @@
|
|||
#include "RayCastingManager.h"
|
||||
|
||||
RayCastingManager::RayCastingManager() {
|
||||
#include "Color.h"
|
||||
#include "RayIntersector.h"
|
||||
#include "Vector3.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
class RayCastingManager::pimpl {
|
||||
public:
|
||||
vector<shared_ptr<RayIntersector>> intersectors;
|
||||
};
|
||||
|
||||
RayCastingManager::RayCastingManager() : impl(new pimpl()) {
|
||||
}
|
||||
|
||||
RayCastingManager::~RayCastingManager() {
|
||||
}
|
||||
|
||||
int RayCastingManager::getIntersectorCount() {
|
||||
return (int)impl->intersectors.size();
|
||||
}
|
||||
|
||||
shared_ptr<RayIntersector> RayCastingManager::getIntersector(int position) {
|
||||
if (position >= 0 && position < getIntersectorCount()) {
|
||||
return impl->intersectors[position];
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RayCastingManager::unregisterAllIntersectors() {
|
||||
impl->intersectors.clear();
|
||||
}
|
||||
|
||||
static bool _cmp_priority(const shared_ptr<RayIntersector> i1, const shared_ptr<RayIntersector> i2) {
|
||||
return i1->getPriority() > i2->getPriority();
|
||||
}
|
||||
|
||||
void RayCastingManager::registerIntersector(shared_ptr<RayIntersector> intersector) {
|
||||
impl->intersectors.push_back(intersector);
|
||||
sort(impl->intersectors.begin(), impl->intersectors.end(), _cmp_priority);
|
||||
}
|
||||
|
||||
Color RayCastingManager::getFinal(const Vector3 &eye, const Vector3 &direction) const {
|
||||
double limit = 10000.0;
|
||||
shared_ptr<RayIntersector> hit;
|
||||
Vector3 hit_location;
|
||||
|
||||
for (auto &intersector : impl->intersectors) {
|
||||
if (intersector->findIntersection(eye, direction, limit, &hit_location)) {
|
||||
limit = hit_location.sub(eye).getNorm();
|
||||
hit = intersector;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
return hit->getColorAtHit(eye, hit_location);
|
||||
} else {
|
||||
return COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,44 @@
|
|||
|
||||
#include "software_global.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
typedef RayCastingResult (*FuncGeneralCastRay)(SoftwareRenderer *renderer, const Vector3 &start,
|
||||
const Vector3 &direction);
|
||||
|
||||
/**
|
||||
* Manager of ray intersectors to perform ray casting on a scenery.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT RayCastingManager {
|
||||
public:
|
||||
RayCastingManager();
|
||||
virtual ~RayCastingManager();
|
||||
|
||||
/**
|
||||
* Get the number of registered intersectors.
|
||||
*/
|
||||
int getIntersectorCount();
|
||||
|
||||
shared_ptr<RayIntersector> getIntersector(int position);
|
||||
|
||||
/**
|
||||
* Clear of all registered intersectors.
|
||||
*/
|
||||
void unregisterAllIntersectors();
|
||||
|
||||
/**
|
||||
* Register a new intersector.
|
||||
*/
|
||||
void registerIntersector(shared_ptr<RayIntersector> intersector);
|
||||
|
||||
/**
|
||||
* Get the final color received along a single ray.
|
||||
*/
|
||||
Color getFinal(const Vector3 &eye, const Vector3 &direction) const;
|
||||
|
||||
private:
|
||||
class pimpl;
|
||||
unique_ptr<pimpl> impl;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
25
src/render/software/RayIntersector.cpp
Normal file
25
src/render/software/RayIntersector.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "RayIntersector.h"
|
||||
|
||||
#include "Color.h"
|
||||
|
||||
RayIntersector::RayIntersector() {
|
||||
}
|
||||
|
||||
RayIntersector::~RayIntersector() {
|
||||
}
|
||||
|
||||
int RayIntersector::getPriority() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool RayIntersector::findIntersection(const Vector3 &, const Vector3 &, double, Vector3 *) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RayIntersector::isInside(const Vector3 &, double *) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Color RayIntersector::getColorAtHit(const Vector3 &, const Vector3 &) const {
|
||||
return COLOR_BLACK;
|
||||
}
|
43
src/render/software/RayIntersector.h
Normal file
43
src/render/software/RayIntersector.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* Abstract class to handle intersection with a ray.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT RayIntersector {
|
||||
public:
|
||||
RayIntersector();
|
||||
virtual ~RayIntersector();
|
||||
|
||||
/**
|
||||
* Get the priority of this intersector.
|
||||
*
|
||||
* Higher priority intersectors are tested first, and should be the easy ones.
|
||||
*/
|
||||
virtual int getPriority() const;
|
||||
|
||||
/**
|
||||
* Find the nearest intersection with the ray (within *limit* length).
|
||||
*
|
||||
* By default, it will perform ray marching, using isInside as intersection checker.
|
||||
*/
|
||||
virtual bool findIntersection(const Vector3 &eye, const Vector3 &direction, double limit, Vector3 *out_hit) const;
|
||||
|
||||
/**
|
||||
* Indicate if a given location is inside a solid volume.
|
||||
*/
|
||||
virtual bool isInside(const Vector3 &location, double *out_distance = nullptr) const;
|
||||
|
||||
/**
|
||||
* Get the incident color for a ray intersection at a given hit point.
|
||||
*
|
||||
* This should already have lighting apply, but not medium traversal between *eye* and *location*.
|
||||
*/
|
||||
virtual Color getColorAtHit(const Vector3 &eye, const Vector3 &location) const;
|
||||
};
|
||||
}
|
||||
}
|
35
src/render/software/SkyIntersector.cpp
Normal file
35
src/render/software/SkyIntersector.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "SkyIntersector.h"
|
||||
|
||||
#include "AtmosphereRenderer.h"
|
||||
#include "AtmosphereResult.h"
|
||||
#include "Color.h"
|
||||
#include "Maths.h"
|
||||
#include "Scenery.h"
|
||||
#include "Vector3.h"
|
||||
#include <cassert>
|
||||
|
||||
SkyIntersector::SkyIntersector(BaseAtmosphereRenderer *atmosphere) : atmosphere(atmosphere) {
|
||||
}
|
||||
|
||||
int SkyIntersector::getPriority() const {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
bool SkyIntersector::findIntersection(const Vector3 &eye, const Vector3 &direction, double, Vector3 *out_hit) const {
|
||||
assert(direction.isNormalized());
|
||||
|
||||
if (eye.y >= Scenery::ATMOSPHERE_WIDTH_SCALED) {
|
||||
// Above atmosphere, intersect right in front of the eye
|
||||
*out_hit = eye.add(direction.scale(0.00001));
|
||||
} else {
|
||||
// Intersect with upper atmosphere boundary
|
||||
// TODO
|
||||
*out_hit = eye.add(direction.scale(0.00001));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Color SkyIntersector::getColorAtHit(const Vector3 &eye, const Vector3 &location) const {
|
||||
return atmosphere->getSkyColor(location.sub(eye).normalize()).final;
|
||||
}
|
28
src/render/software/SkyIntersector.h
Normal file
28
src/render/software/SkyIntersector.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "RayIntersector.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* Ray intersector with sky.
|
||||
*
|
||||
* This will always hit the upper atmosphere limit, in any direction.
|
||||
* If already in the upper atmosphere, it will hit immediately in front of the eye.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT SkyIntersector : public RayIntersector {
|
||||
public:
|
||||
SkyIntersector(BaseAtmosphereRenderer *atmosphere);
|
||||
virtual int getPriority() const override;
|
||||
virtual bool findIntersection(const Vector3 &eye, const Vector3 &direction, double limit,
|
||||
Vector3 *out_hit) const override;
|
||||
virtual Color getColorAtHit(const Vector3 &eye, const Vector3 &location) const override;
|
||||
|
||||
private:
|
||||
BaseAtmosphereRenderer *atmosphere;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -96,21 +96,7 @@ void SoftwareCanvasRenderer::render() {
|
|||
for (int y = 0; y < ny; y++) {
|
||||
for (int x = 0; x < nx; x++) {
|
||||
CanvasPortion *portion = canvas->at(x, y);
|
||||
|
||||
progress->enterSub(2);
|
||||
|
||||
if (not interrupted) {
|
||||
portion->preparePixels();
|
||||
rasterize(portion);
|
||||
}
|
||||
|
||||
if (not interrupted and postprocess_enabled) {
|
||||
applyPixelShader(portion);
|
||||
}
|
||||
|
||||
portion->discardPixels();
|
||||
|
||||
progress->exitSub();
|
||||
renderPortion(portion, progress, &interrupted);
|
||||
}
|
||||
}
|
||||
progress->exitSub();
|
||||
|
@ -174,3 +160,20 @@ void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion) {
|
|||
}
|
||||
progress->exitSub();
|
||||
}
|
||||
|
||||
void SoftwareCanvasRenderer::renderPortion(CanvasPortion *portion, RenderProgress *progress, bool *interrupt) {
|
||||
progress->enterSub(2);
|
||||
|
||||
if (not*interrupt) {
|
||||
portion->preparePixels();
|
||||
rasterize(portion);
|
||||
}
|
||||
|
||||
if (not*interrupt and postprocess_enabled) {
|
||||
applyPixelShader(portion);
|
||||
}
|
||||
|
||||
portion->discardPixels();
|
||||
|
||||
progress->exitSub();
|
||||
}
|
||||
|
|
|
@ -108,6 +108,11 @@ class SOFTWARESHARED_EXPORT SoftwareCanvasRenderer : public SoftwareRenderer {
|
|||
*/
|
||||
void applyPixelShader(CanvasPortion *portion);
|
||||
|
||||
/**
|
||||
* Perform rendering on a single canvas portion.
|
||||
*/
|
||||
virtual void renderPortion(CanvasPortion *portion, RenderProgress *progress, bool *interrupt);
|
||||
|
||||
private:
|
||||
RenderProgress *progress;
|
||||
|
||||
|
|
62
src/render/software/SoftwareRayRenderer.cpp
Normal file
62
src/render/software/SoftwareRayRenderer.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "SoftwareRayRenderer.h"
|
||||
|
||||
#include "CameraDefinition.h"
|
||||
#include "CanvasPortion.h"
|
||||
#include "Color.h"
|
||||
#include "RayCastingManager.h"
|
||||
#include "RenderProgress.h"
|
||||
#include "Scenery.h"
|
||||
#include "SkyIntersector.h"
|
||||
#include "TerrainIntersector.h"
|
||||
#include "Vector3.h"
|
||||
|
||||
class SoftwareRayRenderer::pimpl {
|
||||
public:
|
||||
RayCastingManager manager;
|
||||
};
|
||||
|
||||
SoftwareRayRenderer::SoftwareRayRenderer(Scenery *scenery, bool standard)
|
||||
: SoftwareCanvasRenderer(scenery), impl(new pimpl) {
|
||||
if (standard) {
|
||||
registerStandardIntersectors();
|
||||
}
|
||||
}
|
||||
|
||||
SoftwareRayRenderer::~SoftwareRayRenderer() {
|
||||
}
|
||||
|
||||
void SoftwareRayRenderer::registerStandardIntersectors() {
|
||||
impl->manager.unregisterAllIntersectors();
|
||||
|
||||
impl->manager.registerIntersector(make_shared<SkyIntersector>(getAtmosphereRenderer()));
|
||||
impl->manager.registerIntersector(make_shared<TerrainIntersector>(getTerrainRenderer()));
|
||||
}
|
||||
|
||||
void SoftwareRayRenderer::renderPortion(CanvasPortion *portion, RenderProgress *progress, bool *interrupt) {
|
||||
int width = portion->getWidth();
|
||||
int height = portion->getHeight();
|
||||
|
||||
portion->preparePixels();
|
||||
progress->enterSub(width * height);
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
Vector3 direction =
|
||||
Vector3(1.0, to_double(y) / to_double(height) - 0.5, to_double(x) / to_double(width) - 0.5).normalize();
|
||||
Color color = impl->manager.getFinal(getCameraLocation(), direction);
|
||||
portion->setColor(x, y, color);
|
||||
progress->add();
|
||||
}
|
||||
if (*interrupt) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
portion->discardPixels();
|
||||
progress->exitSub();
|
||||
}
|
||||
|
||||
void SoftwareRayRenderer::prepare() {
|
||||
SoftwareCanvasRenderer::prepare();
|
||||
registerStandardIntersectors();
|
||||
}
|
43
src/render/software/SoftwareRayRenderer.h
Normal file
43
src/render/software/SoftwareRayRenderer.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "SoftwareCanvasRenderer.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* Software rendering using only ray tracing, not rasterization.
|
||||
*
|
||||
* Follows these steps, for each view ray :
|
||||
* - Find a ray intersection with solid matter
|
||||
* - Texture/light the solid matter (may need other secondary rays)
|
||||
* - Apply medium traversal along the ray (e.g. atmosphere)
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT SoftwareRayRenderer : public SoftwareCanvasRenderer {
|
||||
public:
|
||||
SoftwareRayRenderer(Scenery *scenery, bool standard = true);
|
||||
virtual ~SoftwareRayRenderer();
|
||||
|
||||
/**
|
||||
* Register standard scenery intersectors.
|
||||
*/
|
||||
void registerStandardIntersectors();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Render a single canvas portion using ray-tracing.
|
||||
*/
|
||||
virtual void renderPortion(CanvasPortion *portion, RenderProgress *progress, bool *interrupt);
|
||||
|
||||
virtual void prepare() override;
|
||||
|
||||
private:
|
||||
class pimpl;
|
||||
unique_ptr<pimpl> impl;
|
||||
};
|
||||
}
|
||||
}
|
26
src/render/software/TerrainIntersector.cpp
Normal file
26
src/render/software/TerrainIntersector.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "TerrainIntersector.h"
|
||||
|
||||
#include "TerrainRenderer.h"
|
||||
#include "RayCastingResult.h"
|
||||
|
||||
TerrainIntersector::TerrainIntersector(TerrainRenderer *renderer) : renderer(renderer) {
|
||||
}
|
||||
|
||||
int TerrainIntersector::getPriority() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TerrainIntersector::findIntersection(const Vector3 &eye, const Vector3 &direction, double,
|
||||
Vector3 *out_hit) const {
|
||||
auto result = renderer->castRay(eye, direction);
|
||||
if (result.hit) {
|
||||
*out_hit = result.hit_location;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Color TerrainIntersector::getColorAtHit(const Vector3 &, const Vector3 &location) const {
|
||||
return renderer->getFinalColor(location.x, location.z, 0.0001);
|
||||
}
|
25
src/render/software/TerrainIntersector.h
Normal file
25
src/render/software/TerrainIntersector.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "RayIntersector.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* Ray intersector with terrain.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT TerrainIntersector : public RayIntersector {
|
||||
public:
|
||||
TerrainIntersector(TerrainRenderer *renderer);
|
||||
virtual int getPriority() const override;
|
||||
virtual bool findIntersection(const Vector3 &eye, const Vector3 &direction, double limit,
|
||||
Vector3 *out_hit) const override;
|
||||
virtual Color getColorAtHit(const Vector3 &eye, const Vector3 &location) const override;
|
||||
|
||||
private:
|
||||
TerrainRenderer *renderer;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ namespace paysages {
|
|||
namespace software {
|
||||
class SoftwareRenderer;
|
||||
class SoftwareCanvasRenderer;
|
||||
class SoftwareRayRenderer;
|
||||
class RenderConfig;
|
||||
class RenderProgress;
|
||||
|
||||
|
@ -46,6 +47,8 @@ class LightSource;
|
|||
|
||||
class RayCastingManager;
|
||||
class RayCastingResult;
|
||||
class RayIntersector;
|
||||
class SkyIntersector;
|
||||
|
||||
class NightSky;
|
||||
class MoonRenderer;
|
||||
|
|
|
@ -25,6 +25,7 @@ RandomGenerator::RandomGenerator(RandomGenerator::Seed seed) {
|
|||
}
|
||||
}
|
||||
data = new RandomGeneratorPrivate(seed);
|
||||
this->seed = seed;
|
||||
}
|
||||
|
||||
RandomGenerator::~RandomGenerator() {
|
||||
|
|
|
@ -26,6 +26,13 @@ TEST(CameraDefinition, unproject) {
|
|||
point = cam.project(Vector3(-25.1, 8.3, 1.3));
|
||||
point = cam.unproject(point);
|
||||
EXPECT_VECTOR3_COORDS(point, -25.1, 8.3, 1.3);
|
||||
|
||||
cam.setLocationCoords(0.3, 0.8, -2.4);
|
||||
cam.setTargetCoords(5.2, -4.1, 1.5);
|
||||
|
||||
point = cam.project(Vector3(12.4, -1.3, 3.4));
|
||||
point = cam.unproject(point);
|
||||
EXPECT_VECTOR3_COORDS(point, 12.4, -1.3, 3.4);
|
||||
}
|
||||
|
||||
TEST(CameraDefinition, getRealDepth) {
|
||||
|
|
38
src/tests/RayCastingManager_Test.cpp
Normal file
38
src/tests/RayCastingManager_Test.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "RayCastingManager.h"
|
||||
#include "BaseTestCase.h"
|
||||
|
||||
#include "RayIntersector.h"
|
||||
|
||||
class _FakeIntersectorPriority : public RayIntersector {
|
||||
public:
|
||||
_FakeIntersectorPriority(int priority) : priority(priority) {
|
||||
}
|
||||
virtual int getPriority() const override {
|
||||
return priority;
|
||||
}
|
||||
int priority;
|
||||
};
|
||||
|
||||
TEST(RayCastingManager, registerIntersector) {
|
||||
RayCastingManager manager;
|
||||
|
||||
EXPECT_EQ(0, manager.getIntersectorCount());
|
||||
|
||||
manager.registerIntersector(make_shared<_FakeIntersectorPriority>(8));
|
||||
|
||||
ASSERT_EQ(1, manager.getIntersectorCount());
|
||||
EXPECT_EQ(8, ((_FakeIntersectorPriority *)(manager.getIntersector(0).get()))->priority);
|
||||
|
||||
manager.registerIntersector(make_shared<_FakeIntersectorPriority>(15));
|
||||
|
||||
ASSERT_EQ(2, manager.getIntersectorCount());
|
||||
EXPECT_EQ(15, ((_FakeIntersectorPriority *)(manager.getIntersector(0).get()))->priority);
|
||||
EXPECT_EQ(8, ((_FakeIntersectorPriority *)(manager.getIntersector(1).get()))->priority);
|
||||
|
||||
manager.registerIntersector(make_shared<_FakeIntersectorPriority>(2));
|
||||
|
||||
ASSERT_EQ(3, manager.getIntersectorCount());
|
||||
EXPECT_EQ(15, ((_FakeIntersectorPriority *)(manager.getIntersector(0).get()))->priority);
|
||||
EXPECT_EQ(8, ((_FakeIntersectorPriority *)(manager.getIntersector(1).get()))->priority);
|
||||
EXPECT_EQ(2, ((_FakeIntersectorPriority *)(manager.getIntersector(2).get()))->priority);
|
||||
}
|
Loading…
Reference in a new issue