Merge branch 'master' into vegetation
Conflicts: src/basics/Disk.cpp src/basics/Disk.h src/basics/SpaceSegment.cpp src/definition/DefinitionNode.cpp src/definition/DefinitionNode.h src/definition/Scenery.cpp src/definition/Scenery.h src/definition/SurfaceMaterial.cpp src/definition/SurfaceMaterial.h src/definition/TextureLayerDefinition.cpp src/definition/definition_global.h src/interface/commandline/tests.cpp src/render/opengl/OpenGLRenderer.cpp src/render/software/SoftwareCanvasRenderer.cpp src/render/software/SoftwareCanvasRenderer.h src/render/software/SoftwareRenderer.h src/render/software/TerrainRasterizer.cpp src/render/software/TerrainRasterizer.h src/render/software/TerrainRenderer.h src/render/software/software_global.h
This commit is contained in:
commit
9a096ec329
335 changed files with 5430 additions and 8193 deletions
3
Makefile
3
Makefile
|
@ -7,6 +7,9 @@ PATH:=${QTSDK}/bin:${PATH}
|
||||||
|
|
||||||
all:build
|
all:build
|
||||||
|
|
||||||
|
format:
|
||||||
|
find src \( \( -name '*.cpp' -or -name '*.h' \) -and \! -path '*/googletest/*' \) -exec clang-format -i \{\} \;
|
||||||
|
|
||||||
dirs:
|
dirs:
|
||||||
mkdir -p ${BUILDPATH}
|
mkdir -p ${BUILDPATH}
|
||||||
|
|
||||||
|
|
6
src/.clang-format
Normal file
6
src/.clang-format
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
ColumnLimit: 120
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
|
||||||
BoundingBox::BoundingBox()
|
BoundingBox::BoundingBox() {
|
||||||
{
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundingBox::reset()
|
void BoundingBox::reset() {
|
||||||
{
|
|
||||||
empty = 1;
|
empty = 1;
|
||||||
xmin = 10000000000.0;
|
xmin = 10000000000.0;
|
||||||
xmax = -10000000000.0;
|
xmax = -10000000000.0;
|
||||||
|
@ -18,31 +16,24 @@ void BoundingBox::reset()
|
||||||
zmax = -10000000000.0;
|
zmax = -10000000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundingBox::pushPoint(const Vector3 &point)
|
void BoundingBox::pushPoint(const Vector3 &point) {
|
||||||
{
|
|
||||||
empty = 0;
|
empty = 0;
|
||||||
if (point.x < xmin)
|
if (point.x < xmin) {
|
||||||
{
|
|
||||||
xmin = point.x;
|
xmin = point.x;
|
||||||
}
|
}
|
||||||
if (point.x > xmax)
|
if (point.x > xmax) {
|
||||||
{
|
|
||||||
xmax = point.x;
|
xmax = point.x;
|
||||||
}
|
}
|
||||||
if (point.y < ymin)
|
if (point.y < ymin) {
|
||||||
{
|
|
||||||
ymin = point.y;
|
ymin = point.y;
|
||||||
}
|
}
|
||||||
if (point.y > ymax)
|
if (point.y > ymax) {
|
||||||
{
|
|
||||||
ymax = point.y;
|
ymax = point.y;
|
||||||
}
|
}
|
||||||
if (point.z < zmin)
|
if (point.z < zmin) {
|
||||||
{
|
|
||||||
zmin = point.z;
|
zmin = point.z;
|
||||||
}
|
}
|
||||||
if (point.z > zmax)
|
if (point.z > zmax) {
|
||||||
{
|
|
||||||
zmax = point.z;
|
zmax = point.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,14 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT BoundingBox
|
class BASICSSHARED_EXPORT BoundingBox {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
BoundingBox();
|
BoundingBox();
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void pushPoint(const Vector3 &point);
|
void pushPoint(const Vector3 &point);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int empty;
|
int empty;
|
||||||
double xmin;
|
double xmin;
|
||||||
double xmax;
|
double xmax;
|
||||||
|
@ -23,7 +22,6 @@ public:
|
||||||
double zmin;
|
double zmin;
|
||||||
double zmax;
|
double zmax;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,77 +3,56 @@
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
|
|
||||||
CappedCylinder::CappedCylinder()
|
CappedCylinder::CappedCylinder() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CappedCylinder::CappedCylinder(const Vector3 &base, const Vector3 &direction, double radius, double length):
|
CappedCylinder::CappedCylinder(const Vector3 &base, const Vector3 &direction, double radius, double length)
|
||||||
InfiniteCylinder(InfiniteRay(base, direction), radius), length(length)
|
: InfiniteCylinder(InfiniteRay(base, direction), radius), length(length) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CappedCylinder::checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection, Vector3 *second_intersection) const
|
int CappedCylinder::checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection,
|
||||||
{
|
Vector3 *second_intersection) const {
|
||||||
// TODO Apply the caps
|
// TODO Apply the caps
|
||||||
int count = InfiniteCylinder::checkRayIntersection(ray, first_intersection, second_intersection);
|
int count = InfiniteCylinder::checkRayIntersection(ray, first_intersection, second_intersection);
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (count == 2) {
|
||||||
else if (count == 2)
|
if (checkPointProjection(first_intersection)) {
|
||||||
{
|
if (checkPointProjection(second_intersection)) {
|
||||||
if (checkPointProjection(first_intersection))
|
|
||||||
{
|
|
||||||
if (checkPointProjection(second_intersection))
|
|
||||||
{
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (checkPointProjection(second_intersection)) {
|
||||||
{
|
|
||||||
if (checkPointProjection(second_intersection))
|
|
||||||
{
|
|
||||||
*first_intersection = *second_intersection;
|
*first_intersection = *second_intersection;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else // count == 1
|
||||||
else // count == 1
|
|
||||||
{
|
|
||||||
if (checkPointProjection(first_intersection))
|
|
||||||
{
|
{
|
||||||
|
if (checkPointProjection(first_intersection)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CappedCylinder::checkPointProjection(Vector3 *point) const
|
bool CappedCylinder::checkPointProjection(Vector3 *point) const {
|
||||||
{
|
|
||||||
double proj_length = axis.getDirection().dotProduct(point->sub(axis.getOrigin()));
|
double proj_length = axis.getDirection().dotProduct(point->sub(axis.getOrigin()));
|
||||||
return 0.0 <= proj_length && proj_length <= length;
|
return 0.0 <= proj_length && proj_length <= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CappedCylinder::save(PackStream *stream) const
|
void CappedCylinder::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
InfiniteCylinder::save(stream);
|
InfiniteCylinder::save(stream);
|
||||||
stream->write(&length);
|
stream->write(&length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CappedCylinder::load(PackStream *stream)
|
void CappedCylinder::load(PackStream *stream) {
|
||||||
{
|
|
||||||
InfiniteCylinder::load(stream);
|
InfiniteCylinder::load(stream);
|
||||||
stream->read(&length);
|
stream->read(&length);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,14 @@ namespace basics {
|
||||||
/**
|
/**
|
||||||
* Geometric cylinder, with capped ends (not infinite).
|
* Geometric cylinder, with capped ends (not infinite).
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT CappedCylinder: public InfiniteCylinder
|
class BASICSSHARED_EXPORT CappedCylinder : public InfiniteCylinder {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
CappedCylinder();
|
CappedCylinder();
|
||||||
CappedCylinder(const Vector3 &base, const Vector3 &direction, double radius, double length);
|
CappedCylinder(const Vector3 &base, const Vector3 &direction, double radius, double length);
|
||||||
|
|
||||||
inline double getLength() const {return length;}
|
inline double getLength() const {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the intersection between the cylinder and an infinite ray.
|
* Check the intersection between the cylinder and an infinite ray.
|
||||||
|
@ -32,10 +33,9 @@ public:
|
||||||
virtual void save(PackStream *stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream *stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double length;
|
double length;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,16 +11,14 @@ const Color paysages::basics::COLOR_BLUE = {0.0, 0.0, 1.0, 1.0};
|
||||||
const Color paysages::basics::COLOR_WHITE = {1.0, 1.0, 1.0, 1.0};
|
const Color paysages::basics::COLOR_WHITE = {1.0, 1.0, 1.0, 1.0};
|
||||||
const Color paysages::basics::COLOR_GREY = {0.5, 0.5, 0.5, 1.0};
|
const Color paysages::basics::COLOR_GREY = {0.5, 0.5, 0.5, 1.0};
|
||||||
|
|
||||||
void Color::save(PackStream* stream) const
|
void Color::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
stream->write(&r);
|
stream->write(&r);
|
||||||
stream->write(&g);
|
stream->write(&g);
|
||||||
stream->write(&b);
|
stream->write(&b);
|
||||||
stream->write(&a);
|
stream->write(&a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Color::load(PackStream* stream)
|
void Color::load(PackStream *stream) {
|
||||||
{
|
|
||||||
stream->read(&r);
|
stream->read(&r);
|
||||||
stream->read(&g);
|
stream->read(&g);
|
||||||
stream->read(&b);
|
stream->read(&b);
|
||||||
|
|
|
@ -6,15 +6,14 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Color
|
class BASICSSHARED_EXPORT Color {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Color() = default;
|
Color() = default;
|
||||||
Color(const Color &col);
|
Color(const Color &col);
|
||||||
Color(double r, double g, double b, double a=1.0);
|
Color(double r, double g, double b, double a = 1.0);
|
||||||
|
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
|
|
||||||
unsigned int to32BitRGBA() const;
|
unsigned int to32BitRGBA() const;
|
||||||
unsigned int to32BitBGRA() const;
|
unsigned int to32BitBGRA() const;
|
||||||
|
@ -26,16 +25,16 @@ public:
|
||||||
static Color from32BitARGB(unsigned int col);
|
static Color from32BitARGB(unsigned int col);
|
||||||
static Color from32BitABGR(unsigned int col);
|
static Color from32BitABGR(unsigned int col);
|
||||||
|
|
||||||
void mask(const Color& mask);
|
void mask(const Color &mask);
|
||||||
double normalize();
|
double normalize();
|
||||||
double getValue() const;
|
double getValue() const;
|
||||||
double getPower() const;
|
double getPower() const;
|
||||||
void limitPower(double max_power);
|
void limitPower(double max_power);
|
||||||
|
|
||||||
Color add(const Color& other) const;
|
Color add(const Color &other) const;
|
||||||
Color lerp(const Color& other, double f) const;
|
Color lerp(const Color &other, double f) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
double r;
|
double r;
|
||||||
double g;
|
double g;
|
||||||
double b;
|
double b;
|
||||||
|
@ -49,7 +48,6 @@ BASICSSHARED_EXPORT extern const Color COLOR_GREEN;
|
||||||
BASICSSHARED_EXPORT extern const Color COLOR_BLUE;
|
BASICSSHARED_EXPORT extern const Color COLOR_BLUE;
|
||||||
BASICSSHARED_EXPORT extern const Color COLOR_WHITE;
|
BASICSSHARED_EXPORT extern const Color COLOR_WHITE;
|
||||||
BASICSSHARED_EXPORT extern const Color COLOR_GREY;
|
BASICSSHARED_EXPORT extern const Color COLOR_GREY;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,84 +6,59 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef COLOR_H
|
#ifdef COLOR_H
|
||||||
# define METHSPEC inline
|
#define METHSPEC inline
|
||||||
#else
|
#else
|
||||||
# include "Color.h"
|
#include "Color.h"
|
||||||
# define METHSPEC
|
#define METHSPEC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
METHSPEC Color::Color(double r, double g, double b, double a):
|
METHSPEC Color::Color(double r, double g, double b, double a) : r(r), g(g), b(b), a(a) {
|
||||||
r(r), g(g), b(b), a(a)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Color::Color(const Color &col):
|
METHSPEC Color::Color(const Color &col) : r(col.r), g(col.g), b(col.b), a(col.a) {
|
||||||
r(col.r), g(col.g), b(col.b), a(col.a)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC unsigned int Color::to32BitRGBA() const
|
METHSPEC unsigned int Color::to32BitRGBA() const {
|
||||||
{
|
return (((unsigned int)(a * 255.0)) << 24) | (((unsigned int)(b * 255.0)) << 16) |
|
||||||
return (((unsigned int) (a * 255.0)) << 24) | (((unsigned int) (b * 255.0)) << 16) | (((unsigned int) (g * 255.0)) << 8) | ((unsigned int) (r * 255.0));
|
(((unsigned int)(g * 255.0)) << 8) | ((unsigned int)(r * 255.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC unsigned int Color::to32BitBGRA() const
|
METHSPEC unsigned int Color::to32BitBGRA() const {
|
||||||
{
|
return (((unsigned int)(a * 255.0)) << 24) | (((unsigned int)(r * 255.0)) << 16) |
|
||||||
return (((unsigned int) (a * 255.0)) << 24) | (((unsigned int) (r * 255.0)) << 16) | (((unsigned int) (g * 255.0)) << 8) | ((unsigned int) (b * 255.0));
|
(((unsigned int)(g * 255.0)) << 8) | ((unsigned int)(b * 255.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC unsigned int Color::to32BitARGB() const
|
METHSPEC unsigned int Color::to32BitARGB() const {
|
||||||
{
|
return (((unsigned int)(b * 255.0)) << 24) | (((unsigned int)(g * 255.0)) << 16) |
|
||||||
return (((unsigned int) (b * 255.0)) << 24) | (((unsigned int) (g * 255.0)) << 16) | (((unsigned int) (r * 255.0)) << 8) | ((unsigned int) (a * 255.0));
|
(((unsigned int)(r * 255.0)) << 8) | ((unsigned int)(a * 255.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC unsigned int Color::to32BitABGR() const
|
METHSPEC unsigned int Color::to32BitABGR() const {
|
||||||
{
|
return (((unsigned int)(r * 255.0)) << 24) | (((unsigned int)(g * 255.0)) << 16) |
|
||||||
return (((unsigned int) (r * 255.0)) << 24) | (((unsigned int) (g * 255.0)) << 16) | (((unsigned int) (b * 255.0)) << 8) | ((unsigned int) (a * 255.0));
|
(((unsigned int)(b * 255.0)) << 8) | ((unsigned int)(a * 255.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Color Color::from32BitRGBA(unsigned int col)
|
METHSPEC Color Color::from32BitRGBA(unsigned int col) {
|
||||||
{
|
return Color(((double)(col & 0x000000FF)) / 255.0, ((double)((col & 0x0000FF00) >> 8)) / 255.0,
|
||||||
return Color(
|
((double)((col & 0x00FF0000) >> 16)) / 255.0, ((double)((col & 0xFF000000) >> 24)) / 255.0);
|
||||||
((double) (col & 0x000000FF)) / 255.0,
|
|
||||||
((double) ((col & 0x0000FF00) >> 8)) / 255.0,
|
|
||||||
((double) ((col & 0x00FF0000) >> 16)) / 255.0,
|
|
||||||
((double) ((col & 0xFF000000) >> 24)) / 255.0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Color Color::from32BitBGRA(unsigned int col)
|
METHSPEC Color Color::from32BitBGRA(unsigned int col) {
|
||||||
{
|
return Color(((double)(col & 0x000000FF)) / 255.0, ((double)((col & 0x0000FF00) >> 8)) / 255.0,
|
||||||
return Color(
|
((double)((col & 0x00FF0000) >> 16)) / 255.0, ((double)((col & 0xFF000000) >> 24)) / 255.0);
|
||||||
((double) (col & 0x000000FF)) / 255.0,
|
|
||||||
((double) ((col & 0x0000FF00) >> 8)) / 255.0,
|
|
||||||
((double) ((col & 0x00FF0000) >> 16)) / 255.0,
|
|
||||||
((double) ((col & 0xFF000000) >> 24)) / 255.0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Color Color::from32BitARGB(unsigned int col)
|
METHSPEC Color Color::from32BitARGB(unsigned int col) {
|
||||||
{
|
return Color(((double)(col & 0x000000FF)) / 255.0, ((double)((col & 0x0000FF00) >> 8)) / 255.0,
|
||||||
return Color(
|
((double)((col & 0x00FF0000) >> 16)) / 255.0, ((double)((col & 0xFF000000) >> 24)) / 255.0);
|
||||||
((double) (col & 0x000000FF)) / 255.0,
|
|
||||||
((double) ((col & 0x0000FF00) >> 8)) / 255.0,
|
|
||||||
((double) ((col & 0x00FF0000) >> 16)) / 255.0,
|
|
||||||
((double) ((col & 0xFF000000) >> 24)) / 255.0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Color Color::from32BitABGR(unsigned int col)
|
METHSPEC Color Color::from32BitABGR(unsigned int col) {
|
||||||
{
|
return Color(((double)(col & 0x000000FF)) / 255.0, ((double)((col & 0x0000FF00) >> 8)) / 255.0,
|
||||||
return Color(
|
((double)((col & 0x00FF0000) >> 16)) / 255.0, ((double)((col & 0xFF000000) >> 24)) / 255.0);
|
||||||
((double) (col & 0x000000FF)) / 255.0,
|
|
||||||
((double) ((col & 0x0000FF00) >> 8)) / 255.0,
|
|
||||||
((double) ((col & 0x00FF0000) >> 16)) / 255.0,
|
|
||||||
((double) ((col & 0xFF000000) >> 24)) / 255.0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC void Color::mask(const Color& mask)
|
METHSPEC void Color::mask(const Color &mask) {
|
||||||
{
|
|
||||||
double new_a;
|
double new_a;
|
||||||
new_a = a + mask.a - (a * mask.a);
|
new_a = a + mask.a - (a * mask.a);
|
||||||
r = (mask.r * mask.a + r * a - r * a * mask.a) / new_a;
|
r = (mask.r * mask.a + r * a - r * a * mask.a) / new_a;
|
||||||
|
@ -100,8 +75,7 @@ METHSPEC void Color::mask(const Color& mask)
|
||||||
base->a = base->a + mask_weight * (1.0 - base->a);*/
|
base->a = base->a + mask_weight * (1.0 - base->a);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC double Color::normalize()
|
METHSPEC double Color::normalize() {
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
assert(r >= 0.0);
|
assert(r >= 0.0);
|
||||||
assert(g >= 0.0);
|
assert(g >= 0.0);
|
||||||
|
@ -121,16 +95,13 @@ METHSPEC double Color::normalize()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (r > 1.0)
|
if (r > 1.0) {
|
||||||
{
|
|
||||||
r = 1.0;
|
r = 1.0;
|
||||||
}
|
}
|
||||||
if (g > 1.0)
|
if (g > 1.0) {
|
||||||
{
|
|
||||||
g = 1.0;
|
g = 1.0;
|
||||||
}
|
}
|
||||||
if (b > 1.0)
|
if (b > 1.0) {
|
||||||
{
|
|
||||||
b = 1.0;
|
b = 1.0;
|
||||||
}
|
}
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
@ -147,33 +118,27 @@ METHSPEC double Color::normalize()
|
||||||
return max;*/
|
return max;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC double Color::getValue() const
|
METHSPEC double Color::getValue() const {
|
||||||
{
|
|
||||||
double max;
|
double max;
|
||||||
|
|
||||||
max = r;
|
max = r;
|
||||||
if (g > max)
|
if (g > max) {
|
||||||
{
|
|
||||||
max = g;
|
max = g;
|
||||||
}
|
}
|
||||||
if (b > max)
|
if (b > max) {
|
||||||
{
|
|
||||||
max = b;
|
max = b;
|
||||||
}
|
}
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC double Color::getPower() const
|
METHSPEC double Color::getPower() const {
|
||||||
{
|
|
||||||
return r + g + b;
|
return r + g + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC void Color::limitPower(double max_power)
|
METHSPEC void Color::limitPower(double max_power) {
|
||||||
{
|
|
||||||
double power = r + g + b;
|
double power = r + g + b;
|
||||||
|
|
||||||
if (power > max_power)
|
if (power > max_power) {
|
||||||
{
|
|
||||||
double factor = max_power / power;
|
double factor = max_power / power;
|
||||||
|
|
||||||
r *= factor;
|
r *= factor;
|
||||||
|
@ -182,18 +147,12 @@ METHSPEC void Color::limitPower(double max_power)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Color Color::add(const Color& other) const
|
METHSPEC Color Color::add(const Color &other) const {
|
||||||
{
|
|
||||||
return Color(r + other.r, g + other.g, b + other.b, a);
|
return Color(r + other.r, g + other.g, b + other.b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Color Color::lerp(const Color& other, double f) const
|
METHSPEC Color Color::lerp(const Color &other, double f) const {
|
||||||
{
|
Color result(r * (1.0 - f) + other.r * f, g * (1.0 - f) + other.g * f, b * (1.0 - f) + other.b * f,
|
||||||
Color result(
|
a * (1.0 - f) + other.a * f);
|
||||||
r * (1.0 - f) + other.r * f,
|
|
||||||
g * (1.0 - f) + other.g * f,
|
|
||||||
b * (1.0 - f) + other.b * f,
|
|
||||||
a * (1.0 - f) + other.a * f
|
|
||||||
);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,26 +2,26 @@
|
||||||
|
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
|
|
||||||
static inline double _hue2rgb(double p, double q, double t)
|
static inline double _hue2rgb(double p, double q, double t) {
|
||||||
{
|
if (t < 0.0)
|
||||||
if (t < 0.0) t += 1;
|
t += 1;
|
||||||
if (t > 1.0) t -= 1;
|
if (t > 1.0)
|
||||||
if (t < 1.0 / 6.0) return p + (q - p) * 6.0 * t;
|
t -= 1;
|
||||||
if (t < 1.0 / 2.0) return q;
|
if (t < 1.0 / 6.0)
|
||||||
if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
|
return p + (q - p) * 6.0 * t;
|
||||||
|
if (t < 1.0 / 2.0)
|
||||||
|
return q;
|
||||||
|
if (t < 2.0 / 3.0)
|
||||||
|
return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color colorFromHSL(const ColorHSL &col)
|
Color colorFromHSL(const ColorHSL &col) {
|
||||||
{
|
|
||||||
Color result;
|
Color result;
|
||||||
|
|
||||||
if (col.s == 0)
|
if (col.s == 0) {
|
||||||
{
|
|
||||||
result.r = result.g = result.b = col.l;
|
result.r = result.g = result.b = col.l;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
double q = col.l < 0.5 ? col.l * (1.0 + col.s) : col.l + col.s - col.l * col.s;
|
double q = col.l < 0.5 ? col.l * (1.0 + col.s) : col.l + col.s - col.l * col.s;
|
||||||
double p = 2 * col.l - q;
|
double p = 2 * col.l - q;
|
||||||
result.r = _hue2rgb(p, q, col.h + 1.0 / 3.0);
|
result.r = _hue2rgb(p, q, col.h + 1.0 / 3.0);
|
||||||
|
@ -34,8 +34,7 @@ Color colorFromHSL(const ColorHSL &col)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorHSL colorToHSL(const Color &col)
|
ColorHSL colorToHSL(const Color &col) {
|
||||||
{
|
|
||||||
ColorHSL result;
|
ColorHSL result;
|
||||||
double min, max;
|
double min, max;
|
||||||
|
|
||||||
|
@ -47,24 +46,16 @@ ColorHSL colorToHSL(const Color &col)
|
||||||
|
|
||||||
result.h = result.s = result.l = (max + min) / 2.0;
|
result.h = result.s = result.l = (max + min) / 2.0;
|
||||||
|
|
||||||
if (max == min)
|
if (max == min) {
|
||||||
{
|
|
||||||
result.h = result.s = 0.0;
|
result.h = result.s = 0.0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
double d = max - min;
|
double d = max - min;
|
||||||
result.s = result.l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
|
result.s = result.l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
|
||||||
if (max == col.r)
|
if (max == col.r) {
|
||||||
{
|
|
||||||
result.h = (col.g - col.b) / d + (col.g < col.b ? 6.0 : 0);
|
result.h = (col.g - col.b) / d + (col.g < col.b ? 6.0 : 0);
|
||||||
}
|
} else if (max == col.g) {
|
||||||
else if (max == col.g)
|
|
||||||
{
|
|
||||||
result.h = (col.b - col.r) / d + 2.0;
|
result.h = (col.b - col.r) / d + 2.0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
result.h = (col.r - col.g) / d + 4.0;
|
result.h = (col.r - col.g) / d + 4.0;
|
||||||
}
|
}
|
||||||
result.h /= 6.0;
|
result.h /= 6.0;
|
||||||
|
@ -75,8 +66,7 @@ ColorHSL colorToHSL(const Color &col)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorHSL colorHSLFromValues(double h, double s, double l, double a)
|
ColorHSL colorHSLFromValues(double h, double s, double l, double a) {
|
||||||
{
|
|
||||||
ColorHSL result;
|
ColorHSL result;
|
||||||
|
|
||||||
result.h = h;
|
result.h = h;
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
#include "basics_global.h"
|
#include "basics_global.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
double h;
|
double h;
|
||||||
double s;
|
double s;
|
||||||
double l;
|
double l;
|
||||||
|
|
|
@ -2,18 +2,15 @@
|
||||||
|
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
|
|
||||||
ColorProfile::ColorProfile()
|
ColorProfile::ColorProfile() {
|
||||||
{
|
|
||||||
setToneMapping(TONE_MAPPING_UNCHARTED, 1.6);
|
setToneMapping(TONE_MAPPING_UNCHARTED, 1.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorProfile::ColorProfile(ToneMappingOperator tonemapper, double exposure)
|
ColorProfile::ColorProfile(ToneMappingOperator tonemapper, double exposure) {
|
||||||
{
|
|
||||||
setToneMapping(tonemapper, exposure);
|
setToneMapping(tonemapper, exposure);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double _uncharted2Tonemap(double x)
|
static inline double _uncharted2Tonemap(double x) {
|
||||||
{
|
|
||||||
double A = 0.15;
|
double A = 0.15;
|
||||||
double B = 0.50;
|
double B = 0.50;
|
||||||
double C = 0.10;
|
double C = 0.10;
|
||||||
|
@ -24,61 +21,43 @@ static inline double _uncharted2Tonemap(double x)
|
||||||
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
|
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Color _toneMappingUncharted(const Color &pixel, double exposure)
|
static inline Color _toneMappingUncharted(const Color &pixel, double exposure) {
|
||||||
{
|
|
||||||
static const double W = 11.2;
|
static const double W = 11.2;
|
||||||
static const double white_scale = 1.0 / _uncharted2Tonemap(W);
|
static const double white_scale = 1.0 / _uncharted2Tonemap(W);
|
||||||
static const double factor = 1.0 / 2.2;
|
static const double factor = 1.0 / 2.2;
|
||||||
|
|
||||||
Color result(
|
Color result(pow(_uncharted2Tonemap(pixel.r * exposure) * white_scale, factor),
|
||||||
pow(_uncharted2Tonemap(pixel.r * exposure) * white_scale, factor),
|
|
||||||
pow(_uncharted2Tonemap(pixel.g * exposure) * white_scale, factor),
|
pow(_uncharted2Tonemap(pixel.g * exposure) * white_scale, factor),
|
||||||
pow(_uncharted2Tonemap(pixel.b * exposure) * white_scale, factor),
|
pow(_uncharted2Tonemap(pixel.b * exposure) * white_scale, factor), pixel.a);
|
||||||
pixel.a
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Color _toneMappingReinhard(const Color &pixel, double exposure)
|
static inline Color _toneMappingReinhard(const Color &pixel, double exposure) {
|
||||||
{
|
Color result((pixel.r * exposure) / (1.0 + pixel.r * exposure), (pixel.g * exposure) / (1.0 + pixel.g * exposure),
|
||||||
Color result(
|
(pixel.b * exposure) / (1.0 + pixel.b * exposure), pixel.a);
|
||||||
(pixel.r * exposure) / (1.0 + pixel.r * exposure),
|
|
||||||
(pixel.g * exposure) / (1.0 + pixel.g * exposure),
|
|
||||||
(pixel.b * exposure) / (1.0 + pixel.b * exposure),
|
|
||||||
pixel.a
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Color _toneMappingClamp(const Color &pixel)
|
static inline Color _toneMappingClamp(const Color &pixel) {
|
||||||
{
|
Color result(pixel.r > 1.0 ? 1.0 : pixel.r, pixel.g > 1.0 ? 1.0 : pixel.g, pixel.b > 1.0 ? 1.0 : pixel.b, pixel.a);
|
||||||
Color result(
|
|
||||||
pixel.r > 1.0 ? 1.0 : pixel.r,
|
|
||||||
pixel.g > 1.0 ? 1.0 : pixel.g,
|
|
||||||
pixel.b > 1.0 ? 1.0 : pixel.b,
|
|
||||||
pixel.a
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorProfile::setToneMapping(ToneMappingOperator tonemapper, double exposure)
|
void ColorProfile::setToneMapping(ToneMappingOperator tonemapper, double exposure) {
|
||||||
{
|
|
||||||
this->mapper = tonemapper;
|
this->mapper = tonemapper;
|
||||||
this->exposure = exposure;
|
this->exposure = exposure;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorProfile::save(PackStream* stream) const
|
void ColorProfile::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int imapper = (int)mapper;
|
int imapper = (int)mapper;
|
||||||
stream->write(&imapper);
|
stream->write(&imapper);
|
||||||
stream->write(&exposure);
|
stream->write(&exposure);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorProfile::load(PackStream* stream)
|
void ColorProfile::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int imapper = (int)mapper;
|
int imapper = (int)mapper;
|
||||||
stream->read(&imapper);
|
stream->read(&imapper);
|
||||||
stream->read(&exposure);
|
stream->read(&exposure);
|
||||||
|
@ -86,16 +65,13 @@ void ColorProfile::load(PackStream* stream)
|
||||||
mapper = (ToneMappingOperator)imapper;
|
mapper = (ToneMappingOperator)imapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorProfile::copy(ColorProfile* destination) const
|
void ColorProfile::copy(ColorProfile *destination) const {
|
||||||
{
|
|
||||||
destination->mapper = mapper;
|
destination->mapper = mapper;
|
||||||
destination->exposure = exposure;
|
destination->exposure = exposure;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color ColorProfile::apply(const Color &pixel) const
|
Color ColorProfile::apply(const Color &pixel) const {
|
||||||
{
|
switch (mapper) {
|
||||||
switch (mapper)
|
|
||||||
{
|
|
||||||
case TONE_MAPPING_REIHNARD:
|
case TONE_MAPPING_REIHNARD:
|
||||||
return _toneMappingReinhard(pixel, exposure);
|
return _toneMappingReinhard(pixel, exposure);
|
||||||
case TONE_MAPPING_UNCHARTED:
|
case TONE_MAPPING_UNCHARTED:
|
||||||
|
|
|
@ -8,33 +8,26 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT ColorProfile
|
class BASICSSHARED_EXPORT ColorProfile {
|
||||||
{
|
public:
|
||||||
public:
|
typedef enum { TONE_MAPPING_UNCHARTED, TONE_MAPPING_REIHNARD, TONE_MAPPING_CLAMP } ToneMappingOperator;
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TONE_MAPPING_UNCHARTED,
|
|
||||||
TONE_MAPPING_REIHNARD,
|
|
||||||
TONE_MAPPING_CLAMP
|
|
||||||
} ToneMappingOperator;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ColorProfile();
|
ColorProfile();
|
||||||
ColorProfile(ToneMappingOperator tonemapper, double exposure);
|
ColorProfile(ToneMappingOperator tonemapper, double exposure);
|
||||||
|
|
||||||
void setToneMapping(ToneMappingOperator tonemapper, double exposure);
|
void setToneMapping(ToneMappingOperator tonemapper, double exposure);
|
||||||
|
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
void copy(ColorProfile* destination) const;
|
void copy(ColorProfile *destination) const;
|
||||||
|
|
||||||
Color apply(const Color &pixel) const;
|
Color apply(const Color &pixel) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ToneMappingOperator mapper;
|
ToneMappingOperator mapper;
|
||||||
double exposure;
|
double exposure;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,167 +5,123 @@
|
||||||
|
|
||||||
const int MAX_NB_POINTS = 30;
|
const int MAX_NB_POINTS = 30;
|
||||||
|
|
||||||
Curve::Curve()
|
Curve::Curve() {
|
||||||
{
|
|
||||||
nbpoints = 0;
|
nbpoints = 0;
|
||||||
default_value = 0.0;
|
default_value = 0.0;
|
||||||
points = new CurvePoint[MAX_NB_POINTS];
|
points = new CurvePoint[MAX_NB_POINTS];
|
||||||
}
|
}
|
||||||
|
|
||||||
Curve::~Curve()
|
Curve::~Curve() {
|
||||||
{
|
|
||||||
delete[] points;
|
delete[] points;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::copy(Curve* destination) const
|
void Curve::copy(Curve *destination) const {
|
||||||
{
|
|
||||||
destination->nbpoints = nbpoints;
|
destination->nbpoints = nbpoints;
|
||||||
destination->default_value = default_value;
|
destination->default_value = default_value;
|
||||||
for (int i = 0; i < nbpoints; i++)
|
for (int i = 0; i < nbpoints; i++) {
|
||||||
{
|
|
||||||
destination->points[i] = points[i];
|
destination->points[i] = points[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::save(PackStream* stream) const
|
void Curve::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
stream->write(&default_value);
|
stream->write(&default_value);
|
||||||
stream->write(&nbpoints);
|
stream->write(&nbpoints);
|
||||||
for (int i = 0; i < nbpoints; i++)
|
for (int i = 0; i < nbpoints; i++) {
|
||||||
{
|
|
||||||
stream->write(&points[i].position);
|
stream->write(&points[i].position);
|
||||||
stream->write(&points[i].value);
|
stream->write(&points[i].value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::load(PackStream* stream)
|
void Curve::load(PackStream *stream) {
|
||||||
{
|
|
||||||
stream->read(&default_value);
|
stream->read(&default_value);
|
||||||
stream->read(&nbpoints);
|
stream->read(&nbpoints);
|
||||||
for (int i = 0; i < nbpoints; i++)
|
for (int i = 0; i < nbpoints; i++) {
|
||||||
{
|
|
||||||
stream->read(&points[i].position);
|
stream->read(&points[i].position);
|
||||||
stream->read(&points[i].value);
|
stream->read(&points[i].value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::clear()
|
void Curve::clear() {
|
||||||
{
|
|
||||||
nbpoints = 0;
|
nbpoints = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::setDefault(double value)
|
void Curve::setDefault(double value) {
|
||||||
{
|
|
||||||
default_value = value;
|
default_value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Curve::addPoint(const CurvePoint &point)
|
int Curve::addPoint(const CurvePoint &point) {
|
||||||
{
|
if (nbpoints < MAX_NB_POINTS) {
|
||||||
if (nbpoints < MAX_NB_POINTS)
|
|
||||||
{
|
|
||||||
points[nbpoints] = point;
|
points[nbpoints] = point;
|
||||||
return nbpoints++;
|
return nbpoints++;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Curve::addPoint(double position, double value)
|
int Curve::addPoint(double position, double value) {
|
||||||
{
|
|
||||||
CurvePoint point = {position, value};
|
CurvePoint point = {position, value};
|
||||||
return addPoint(point);
|
return addPoint(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurvePoint Curve::getPoint(int number) const
|
CurvePoint Curve::getPoint(int number) const {
|
||||||
{
|
if (number >= 0 && number < nbpoints) {
|
||||||
if (number >= 0 && number < nbpoints)
|
|
||||||
{
|
|
||||||
return points[number];
|
return points[number];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return {0.0, 0.0};
|
return {0.0, 0.0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Curve::getPoint(int number, CurvePoint *point) const
|
bool Curve::getPoint(int number, CurvePoint *point) const {
|
||||||
{
|
if (number >= 0 && number < nbpoints) {
|
||||||
if (number >= 0 && number < nbpoints)
|
|
||||||
{
|
|
||||||
*point = points[number];
|
*point = points[number];
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::setPoint(int number, const CurvePoint &point)
|
void Curve::setPoint(int number, const CurvePoint &point) {
|
||||||
{
|
if (number >= 0 && number < nbpoints) {
|
||||||
if (number >= 0 && number < nbpoints)
|
|
||||||
{
|
|
||||||
points[number] = point;
|
points[number] = point;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::removePoint(int number)
|
void Curve::removePoint(int number) {
|
||||||
{
|
if (number >= 0 && number < nbpoints) {
|
||||||
if (number >= 0 && number < nbpoints)
|
if (nbpoints > 0 && number < nbpoints - 1) {
|
||||||
{
|
|
||||||
if (nbpoints > 0 && number < nbpoints - 1)
|
|
||||||
{
|
|
||||||
memmove(points + number, points + number + 1, sizeof(CurvePoint) * (nbpoints - number - 1));
|
memmove(points + number, points + number + 1, sizeof(CurvePoint) * (nbpoints - number - 1));
|
||||||
}
|
}
|
||||||
nbpoints--;
|
nbpoints--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int _point_compare(const void* part1, const void* part2)
|
int _point_compare(const void *part1, const void *part2) {
|
||||||
{
|
if (((CurvePoint *)part1)->position > ((CurvePoint *)part2)->position) {
|
||||||
if (((CurvePoint*)part1)->position > ((CurvePoint*)part2)->position)
|
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curve::validate()
|
void Curve::validate() {
|
||||||
{
|
if (nbpoints > 1) {
|
||||||
if (nbpoints > 1)
|
|
||||||
{
|
|
||||||
qsort(points, nbpoints, sizeof(CurvePoint), _point_compare);
|
qsort(points, nbpoints, sizeof(CurvePoint), _point_compare);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Curve::getValue(double position) const
|
double Curve::getValue(double position) const {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
double fact;
|
double fact;
|
||||||
|
|
||||||
if (nbpoints == 0)
|
if (nbpoints == 0) {
|
||||||
{
|
|
||||||
return default_value;
|
return default_value;
|
||||||
}
|
} else if (nbpoints == 1 || position <= points[0].position) {
|
||||||
else if (nbpoints == 1 || position <= points[0].position)
|
|
||||||
{
|
|
||||||
return points[0].value;
|
return points[0].value;
|
||||||
}
|
} else if (position >= points[nbpoints - 1].position) {
|
||||||
else if (position >= points[nbpoints - 1].position)
|
|
||||||
{
|
|
||||||
return points[nbpoints - 1].value;
|
return points[nbpoints - 1].value;
|
||||||
}
|
} else {
|
||||||
else
|
for (i = 1; i < nbpoints; i++) {
|
||||||
{
|
if (position < points[i].position) {
|
||||||
for (i = 1; i < nbpoints; i++)
|
|
||||||
{
|
|
||||||
if (position < points[i].position)
|
|
||||||
{
|
|
||||||
fact = (position - points[i - 1].position) / (points[i].position - points[i - 1].position);
|
fact = (position - points[i - 1].position) / (points[i].position - points[i - 1].position);
|
||||||
return points[i - 1].value + (points[i].value - points[i - 1].value) * fact;
|
return points[i - 1].value + (points[i].value - points[i - 1].value) * fact;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,18 +11,19 @@ typedef struct {
|
||||||
double value;
|
double value;
|
||||||
} CurvePoint;
|
} CurvePoint;
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Curve
|
class BASICSSHARED_EXPORT Curve {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Curve();
|
Curve();
|
||||||
~Curve();
|
~Curve();
|
||||||
|
|
||||||
void copy(Curve* destination) const;
|
void copy(Curve *destination) const;
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
void validate();
|
void validate();
|
||||||
|
|
||||||
inline int getPointCount() const {return nbpoints;}
|
inline int getPointCount() const {
|
||||||
|
return nbpoints;
|
||||||
|
}
|
||||||
CurvePoint getPoint(int number) const;
|
CurvePoint getPoint(int number) const;
|
||||||
bool getPoint(int number, CurvePoint *point) const;
|
bool getPoint(int number, CurvePoint *point) const;
|
||||||
|
|
||||||
|
@ -35,12 +36,11 @@ public:
|
||||||
void setPoint(int number, const CurvePoint &point);
|
void setPoint(int number, const CurvePoint &point);
|
||||||
void removePoint(int number);
|
void removePoint(int number);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double default_value;
|
double default_value;
|
||||||
int nbpoints;
|
int nbpoints;
|
||||||
CurvePoint* points;
|
CurvePoint *points;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,37 +2,29 @@
|
||||||
|
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
|
|
||||||
Disk::Disk(const Vector3 &point, const Vector3 &normal, double radius):
|
Disk::Disk(const Vector3 &point, const Vector3 &normal, double radius) : InfinitePlane(point, normal), radius(radius) {
|
||||||
InfinitePlane(point, normal), radius(radius)
|
|
||||||
{
|
|
||||||
radius2 = radius * radius;
|
radius2 = radius * radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::checkRayIntersection(const InfiniteRay &ray, Vector3 *intersection) const
|
int Disk::checkRayIntersection(const InfiniteRay &ray, Vector3 *intersection) const {
|
||||||
{
|
|
||||||
int result = InfinitePlane::checkRayIntersection(ray, intersection);
|
int result = InfinitePlane::checkRayIntersection(ray, intersection);
|
||||||
|
|
||||||
if (result == 1)
|
if (result == 1) {
|
||||||
{
|
|
||||||
Vector3 v = intersection->sub(getPoint());
|
Vector3 v = intersection->sub(getPoint());
|
||||||
double d2 = v.dotProduct(v);
|
double d2 = v.dotProduct(v);
|
||||||
return (d2 <= radius2) ? 1 : 0;
|
return (d2 <= radius2) ? 1 : 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::save(PackStream *stream) const
|
void Disk::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
InfinitePlane::save(stream);
|
InfinitePlane::save(stream);
|
||||||
stream->write(&radius);
|
stream->write(&radius);
|
||||||
stream->write(&radius2);
|
stream->write(&radius2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::load(PackStream *stream)
|
void Disk::load(PackStream *stream) {
|
||||||
{
|
|
||||||
InfinitePlane::load(stream);
|
InfinitePlane::load(stream);
|
||||||
stream->read(&radius);
|
stream->read(&radius);
|
||||||
stream->read(&radius2);
|
stream->read(&radius2);
|
||||||
|
|
|
@ -11,13 +11,14 @@ namespace basics {
|
||||||
/**
|
/**
|
||||||
* Geometric plane disk.
|
* Geometric plane disk.
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT Disk: public InfinitePlane
|
class BASICSSHARED_EXPORT Disk : public InfinitePlane {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Disk() = default;
|
Disk() = default;
|
||||||
Disk(const Vector3 &point, const Vector3 &normal, double radius);
|
Disk(const Vector3 &point, const Vector3 &normal, double radius);
|
||||||
|
|
||||||
inline double getRadius() const {return radius;}
|
inline double getRadius() const {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the intersection between the disk and an infinite ray.
|
* Check the intersection between the disk and an infinite ray.
|
||||||
|
@ -26,16 +27,15 @@ public:
|
||||||
*
|
*
|
||||||
* Returns -1 if the ray shares a segment with the disk.
|
* Returns -1 if the ray shares a segment with the disk.
|
||||||
*/
|
*/
|
||||||
int checkRayIntersection(const InfiniteRay& ray, Vector3 *intersection) const;
|
int checkRayIntersection(const InfiniteRay &ray, Vector3 *intersection) const;
|
||||||
|
|
||||||
void save(PackStream *stream) const override;
|
void save(PackStream *stream) const override;
|
||||||
void load(PackStream *stream) override;
|
void load(PackStream *stream) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double radius;
|
double radius;
|
||||||
double radius2;
|
double radius2;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "FractalNoise.h"
|
#include "FractalNoise.h"
|
||||||
|
|
||||||
FractalNoise::FractalNoise()
|
FractalNoise::FractalNoise() {
|
||||||
{
|
|
||||||
scaling = 1.0;
|
scaling = 1.0;
|
||||||
height = 1.0;
|
height = 1.0;
|
||||||
step_scaling = 2.0;
|
step_scaling = 2.0;
|
||||||
|
@ -10,47 +9,39 @@ FractalNoise::FractalNoise()
|
||||||
ridge = 0.0;
|
ridge = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FractalNoise::~FractalNoise()
|
FractalNoise::~FractalNoise() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FractalNoise::setScaling(double scaling, double height)
|
void FractalNoise::setScaling(double scaling, double height) {
|
||||||
{
|
|
||||||
this->scaling = scaling < 0.00000001 ? 0.0 : 1.0 / scaling;
|
this->scaling = scaling < 0.00000001 ? 0.0 : 1.0 / scaling;
|
||||||
this->height = scaling * height;
|
this->height = scaling * height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FractalNoise::setStep(double scaling_factor, double height_factor)
|
void FractalNoise::setStep(double scaling_factor, double height_factor) {
|
||||||
{
|
|
||||||
this->step_scaling = scaling_factor < 0.00000001 ? 0.0 : 1.0 / scaling_factor;
|
this->step_scaling = scaling_factor < 0.00000001 ? 0.0 : 1.0 / scaling_factor;
|
||||||
this->step_height = scaling_factor * height_factor;
|
this->step_height = scaling_factor * height_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FractalNoise::setSlope(double slope_factor)
|
void FractalNoise::setSlope(double slope_factor) {
|
||||||
{
|
|
||||||
this->slope = slope_factor;
|
this->slope = slope_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FractalNoise::setRidge(double ridge_factor)
|
void FractalNoise::setRidge(double ridge_factor) {
|
||||||
{
|
|
||||||
this->ridge = ridge_factor;
|
this->ridge = ridge_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FractalNoise::setState(const NoiseState &state)
|
void FractalNoise::setState(const NoiseState &state) {
|
||||||
{
|
|
||||||
state.copy(&this->state);
|
state.copy(&this->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
double FractalNoise::get1d(double detail, double x) const
|
double FractalNoise::get1d(double detail, double x) const {
|
||||||
{
|
|
||||||
double current_scaling = scaling;
|
double current_scaling = scaling;
|
||||||
double current_height = height;
|
double current_height = height;
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
int state_level_count = state.level_offsets.size();
|
int state_level_count = state.level_offsets.size();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (current_height >= detail)
|
while (current_height >= detail) {
|
||||||
{
|
|
||||||
const NoiseState::NoiseOffset &offset = state.level_offsets[i];
|
const NoiseState::NoiseOffset &offset = state.level_offsets[i];
|
||||||
|
|
||||||
result += getBase1d(offset.x + x * current_scaling) * current_height;
|
result += getBase1d(offset.x + x * current_scaling) * current_height;
|
||||||
|
@ -59,8 +50,7 @@ double FractalNoise::get1d(double detail, double x) const
|
||||||
current_height *= step_height;
|
current_height *= step_height;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
if (i >= state_level_count)
|
if (i >= state_level_count) {
|
||||||
{
|
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,16 +58,14 @@ double FractalNoise::get1d(double detail, double x) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FractalNoise::get2d(double detail, double x, double y) const
|
double FractalNoise::get2d(double detail, double x, double y) const {
|
||||||
{
|
|
||||||
double current_scaling = scaling;
|
double current_scaling = scaling;
|
||||||
double current_height = height;
|
double current_height = height;
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
int state_level_count = state.level_offsets.size();
|
int state_level_count = state.level_offsets.size();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (current_height >= detail)
|
while (current_height >= detail) {
|
||||||
{
|
|
||||||
const NoiseState::NoiseOffset &offset = state.level_offsets[i];
|
const NoiseState::NoiseOffset &offset = state.level_offsets[i];
|
||||||
|
|
||||||
result += getBase2d(offset.x + x * current_scaling, offset.y + y * current_scaling) * current_height;
|
result += getBase2d(offset.x + x * current_scaling, offset.y + y * current_scaling) * current_height;
|
||||||
|
@ -86,8 +74,7 @@ double FractalNoise::get2d(double detail, double x, double y) const
|
||||||
current_height *= step_height;
|
current_height *= step_height;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
if (i >= state_level_count)
|
if (i >= state_level_count) {
|
||||||
{
|
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,26 +82,25 @@ double FractalNoise::get2d(double detail, double x, double y) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FractalNoise::get3d(double detail, double x, double y, double z) const
|
double FractalNoise::get3d(double detail, double x, double y, double z) const {
|
||||||
{
|
|
||||||
double current_scaling = scaling;
|
double current_scaling = scaling;
|
||||||
double current_height = height;
|
double current_height = height;
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
int state_level_count = state.level_offsets.size();
|
int state_level_count = state.level_offsets.size();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (current_height >= detail)
|
while (current_height >= detail) {
|
||||||
{
|
|
||||||
const NoiseState::NoiseOffset &offset = state.level_offsets[i];
|
const NoiseState::NoiseOffset &offset = state.level_offsets[i];
|
||||||
|
|
||||||
result += getBase3d(offset.x + x * current_scaling, offset.y + y * current_scaling, offset.z + z * current_scaling) * current_height;
|
result +=
|
||||||
|
getBase3d(offset.x + x * current_scaling, offset.y + y * current_scaling, offset.z + z * current_scaling) *
|
||||||
|
current_height;
|
||||||
|
|
||||||
current_scaling *= step_scaling;
|
current_scaling *= step_scaling;
|
||||||
current_height *= step_height;
|
current_height *= step_height;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
if (i >= state_level_count)
|
if (i >= state_level_count) {
|
||||||
{
|
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,12 +108,10 @@ double FractalNoise::get3d(double detail, double x, double y, double z) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FractalNoise::getBase1d(double x) const
|
double FractalNoise::getBase1d(double x) const {
|
||||||
{
|
|
||||||
return getBase2d(x, 0.0);
|
return getBase2d(x, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double FractalNoise::getBase2d(double x, double y) const
|
double FractalNoise::getBase2d(double x, double y) const {
|
||||||
{
|
|
||||||
return getBase3d(x, y, 0.0);
|
return getBase3d(x, y, 0.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,13 @@ namespace basics {
|
||||||
/*!
|
/*!
|
||||||
* \brief Fractal noise generator, based on a sum of simple noise functions.
|
* \brief Fractal noise generator, based on a sum of simple noise functions.
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT FractalNoise
|
class BASICSSHARED_EXPORT FractalNoise {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
FractalNoise();
|
FractalNoise();
|
||||||
virtual ~FractalNoise();
|
virtual ~FractalNoise();
|
||||||
|
|
||||||
void setScaling(double scaling, double height=1.0);
|
void setScaling(double scaling, double height = 1.0);
|
||||||
void setStep(double scaling_factor, double height_factor=1.0);
|
void setStep(double scaling_factor, double height_factor = 1.0);
|
||||||
void setSlope(double slope_factor);
|
void setSlope(double slope_factor);
|
||||||
void setRidge(double ridge_factor);
|
void setRidge(double ridge_factor);
|
||||||
void setState(const NoiseState &state);
|
void setState(const NoiseState &state);
|
||||||
|
@ -31,7 +30,7 @@ public:
|
||||||
virtual double getBase2d(double x, double y) const;
|
virtual double getBase2d(double x, double y) const;
|
||||||
virtual double getBase3d(double x, double y, double z) const = 0;
|
virtual double getBase3d(double x, double y, double z) const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NoiseState state;
|
NoiseState state;
|
||||||
|
|
||||||
double scaling;
|
double scaling;
|
||||||
|
@ -41,7 +40,6 @@ private:
|
||||||
double slope;
|
double slope;
|
||||||
double ridge;
|
double ridge;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,15 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
|
||||||
double Geometry::get2DAngle(double x, double y)
|
double Geometry::get2DAngle(double x, double y) {
|
||||||
{
|
|
||||||
double nx, ny, d, ret;
|
double nx, ny, d, ret;
|
||||||
|
|
||||||
if (x == 0.0)
|
if (x == 0.0) {
|
||||||
{
|
if (y == 0.0) {
|
||||||
if (y == 0.0)
|
|
||||||
{
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
} else if (y < 0.0) {
|
||||||
else if (y < 0.0)
|
|
||||||
{
|
|
||||||
return 3.0 * M_PI_2;
|
return 3.0 * M_PI_2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return M_PI_2;
|
return M_PI_2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,54 +21,46 @@ double Geometry::get2DAngle(double x, double y)
|
||||||
ny = y / d;
|
ny = y / d;
|
||||||
|
|
||||||
ret = asin(ny);
|
ret = asin(ny);
|
||||||
if (nx < 0.0)
|
if (nx < 0.0) {
|
||||||
{
|
|
||||||
ret = M_PI - ret;
|
ret = M_PI - ret;
|
||||||
}
|
}
|
||||||
return ret < 0.0 ? ret + 2.0 * M_PI : ret;
|
return ret < 0.0 ? ret + 2.0 * M_PI : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Geometry::getNormalFromTriangle(const Vector3 ¢er, const Vector3 &bottom, const Vector3 &right)
|
Vector3 Geometry::getNormalFromTriangle(const Vector3 ¢er, const Vector3 &bottom, const Vector3 &right) {
|
||||||
{
|
|
||||||
Vector3 dx = right.sub(center);
|
Vector3 dx = right.sub(center);
|
||||||
Vector3 dz = bottom.sub(center);
|
Vector3 dz = bottom.sub(center);
|
||||||
return dz.crossProduct(dx).normalize();
|
return dz.crossProduct(dx).normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
double Geometry::getDistance2D(double x1, double y1, double x2, double y2)
|
double Geometry::getDistance2D(double x1, double y1, double x2, double y2) {
|
||||||
{
|
|
||||||
double dx = x2 - x1;
|
double dx = x2 - x1;
|
||||||
double dy = y2 - y1;
|
double dy = y2 - y1;
|
||||||
return sqrt(dx * dx + dy * dy);
|
return sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Geometry::rayIntersectSphere(const Vector3 &ray_point, const Vector3 &ray_direction, const Vector3 &sphere_center, double sphere_radius, Vector3 *hit1, Vector3 *hit2)
|
int Geometry::rayIntersectSphere(const Vector3 &ray_point, const Vector3 &ray_direction, const Vector3 &sphere_center,
|
||||||
{
|
double sphere_radius, Vector3 *hit1, Vector3 *hit2) {
|
||||||
Vector3 ray_direction_sphere = ray_point.sub(sphere_center);
|
Vector3 ray_direction_sphere = ray_point.sub(sphere_center);
|
||||||
double a, b, c, d;
|
double a, b, c, d;
|
||||||
|
|
||||||
a = ray_direction.x * ray_direction.x + ray_direction.y * ray_direction.y + ray_direction.z * ray_direction.z;
|
a = ray_direction.x * ray_direction.x + ray_direction.y * ray_direction.y + ray_direction.z * ray_direction.z;
|
||||||
b = 2 * (ray_direction.x * ray_direction_sphere.x + ray_direction.y * ray_direction_sphere.y + ray_direction.z * ray_direction_sphere.z);
|
b = 2 * (ray_direction.x * ray_direction_sphere.x + ray_direction.y * ray_direction_sphere.y +
|
||||||
c = ray_direction_sphere.x * ray_direction_sphere.x + ray_direction_sphere.y * ray_direction_sphere.y + ray_direction_sphere.z * ray_direction_sphere.z - sphere_radius * sphere_radius;
|
ray_direction.z * ray_direction_sphere.z);
|
||||||
|
c = ray_direction_sphere.x * ray_direction_sphere.x + ray_direction_sphere.y * ray_direction_sphere.y +
|
||||||
|
ray_direction_sphere.z * ray_direction_sphere.z - sphere_radius * sphere_radius;
|
||||||
d = b * b - 4 * a * c;
|
d = b * b - 4 * a * c;
|
||||||
|
|
||||||
if (d < 0.0)
|
if (d < 0.0) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (d > 0.0) {
|
||||||
else if (d > 0.0)
|
if (hit1 && hit2) {
|
||||||
{
|
|
||||||
if (hit1 && hit2)
|
|
||||||
{
|
|
||||||
*hit1 = ray_point.add(ray_direction.scale((-b - sqrt(d)) / (2 * a)));
|
*hit1 = ray_point.add(ray_direction.scale((-b - sqrt(d)) / (2 * a)));
|
||||||
*hit2 = ray_point.add(ray_direction.scale((-b + sqrt(d)) / (2 * a)));
|
*hit2 = ray_point.add(ray_direction.scale((-b + sqrt(d)) / (2 * a)));
|
||||||
}
|
}
|
||||||
return 2;
|
return 2;
|
||||||
}
|
} else {
|
||||||
else
|
if (hit1) {
|
||||||
{
|
|
||||||
if (hit1)
|
|
||||||
{
|
|
||||||
*hit1 = ray_point.add(ray_direction.scale(-b / (2 * a)));
|
*hit1 = ray_point.add(ray_direction.scale(-b / (2 * a)));
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -6,15 +6,14 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Geometry
|
class BASICSSHARED_EXPORT Geometry {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
static double get2DAngle(double x, double y);
|
static double get2DAngle(double x, double y);
|
||||||
static Vector3 getNormalFromTriangle(const Vector3 ¢er, const Vector3 &bottom, const Vector3 &right);
|
static Vector3 getNormalFromTriangle(const Vector3 ¢er, const Vector3 &bottom, const Vector3 &right);
|
||||||
static double getDistance2D(double x1, double y1, double x2, double y2);
|
static double getDistance2D(double x1, double y1, double x2, double y2);
|
||||||
static int rayIntersectSphere(const Vector3 &ray_point, const Vector3 &ray_direction, const Vector3 &sphere_center, double sphere_radius, Vector3 *hit1, Vector3 *hit2);
|
static int rayIntersectSphere(const Vector3 &ray_point, const Vector3 &ray_direction, const Vector3 &sphere_center,
|
||||||
|
double sphere_radius, Vector3 *hit1, Vector3 *hit2);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,14 @@
|
||||||
|
|
||||||
#define EPS 1E-8
|
#define EPS 1E-8
|
||||||
|
|
||||||
InfiniteCylinder::InfiniteCylinder()
|
InfiniteCylinder::InfiniteCylinder() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InfiniteCylinder::InfiniteCylinder(const InfiniteRay &axis, double radius):
|
InfiniteCylinder::InfiniteCylinder(const InfiniteRay &axis, double radius) : axis(axis), radius(radius) {
|
||||||
axis(axis), radius(radius)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int InfiniteCylinder::checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection, Vector3 *second_intersection) const
|
int InfiniteCylinder::checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection,
|
||||||
{
|
Vector3 *second_intersection) const {
|
||||||
/*
|
/*
|
||||||
* Original algorithm has been altered, because it didn't work with non-(0,0,0) axis origin.
|
* Original algorithm has been altered, because it didn't work with non-(0,0,0) axis origin.
|
||||||
* Maybe some optimizations could be made from this.
|
* Maybe some optimizations could be made from this.
|
||||||
|
@ -27,108 +24,108 @@ int InfiniteCylinder::checkRayIntersection(const InfiniteRay &ray, Vector3 *firs
|
||||||
|
|
||||||
/* choose U, V so that U,V,F is orthonormal set */
|
/* choose U, V so that U,V,F is orthonormal set */
|
||||||
|
|
||||||
if ( fabs(F.x) > fabs(F.y) && fabs(F.x) > fabs(F.z) )
|
if (fabs(F.x) > fabs(F.y) && fabs(F.x) > fabs(F.z)) {
|
||||||
{
|
length = sqrt(F.x * F.x + F.y * F.y);
|
||||||
length = sqrt(F.x*F.x+F.y*F.y);
|
invLength = 1.0 / length;
|
||||||
invLength = 1.0/length;
|
U.x = -F.y * invLength;
|
||||||
U.x = -F.y*invLength;
|
U.y = +F.x * invLength;
|
||||||
U.y = +F.x*invLength;
|
|
||||||
U.z = 0.0;
|
U.z = 0.0;
|
||||||
prod = -F.z*invLength;
|
prod = -F.z * invLength;
|
||||||
V.x = F.x*prod;
|
V.x = F.x * prod;
|
||||||
V.y = F.y*prod;
|
V.y = F.y * prod;
|
||||||
V.z = length;
|
V.z = length;
|
||||||
}
|
} else {
|
||||||
else
|
length = sqrt(F.y * F.y + F.z * F.z);
|
||||||
{
|
invLength = 1.0 / length;
|
||||||
length = sqrt(F.y*F.y+F.z*F.z);
|
|
||||||
invLength = 1.0/length;
|
|
||||||
U.x = 0.0;
|
U.x = 0.0;
|
||||||
U.y = -F.z*invLength;
|
U.y = -F.z * invLength;
|
||||||
U.z = +F.y*invLength;
|
U.z = +F.y * invLength;
|
||||||
prod = -F.x*invLength;
|
prod = -F.x * invLength;
|
||||||
V.x = length;
|
V.x = length;
|
||||||
V.y = F.y*prod;
|
V.y = F.y * prod;
|
||||||
V.z = F.z*prod;
|
V.z = F.z * prod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* orthonormal matrix */
|
/* orthonormal matrix */
|
||||||
R[0][0] = U.x; R[0][1] = U.y; R[0][2] = U.z;
|
R[0][0] = U.x;
|
||||||
R[1][0] = V.x; R[1][1] = V.y; R[1][2] = V.z;
|
R[0][1] = U.y;
|
||||||
R[2][0] = F.x; R[2][1] = F.y; R[2][2] = F.z;
|
R[0][2] = U.z;
|
||||||
|
R[1][0] = V.x;
|
||||||
|
R[1][1] = V.y;
|
||||||
|
R[1][2] = V.z;
|
||||||
|
R[2][0] = F.x;
|
||||||
|
R[2][1] = F.y;
|
||||||
|
R[2][2] = F.z;
|
||||||
|
|
||||||
/* matrix A */
|
/* matrix A */
|
||||||
A[0][0] = R[0][0]*R[0][0]+R[1][0]*R[1][0];
|
A[0][0] = R[0][0] * R[0][0] + R[1][0] * R[1][0];
|
||||||
A[0][1] = R[0][0]*R[0][1]+R[1][0]*R[1][1];
|
A[0][1] = R[0][0] * R[0][1] + R[1][0] * R[1][1];
|
||||||
A[0][2] = R[0][0]*R[0][2]+R[1][0]*R[1][2];
|
A[0][2] = R[0][0] * R[0][2] + R[1][0] * R[1][2];
|
||||||
|
|
||||||
A[1][0] = R[0][1]*R[0][0]+R[1][1]*R[1][0];
|
A[1][0] = R[0][1] * R[0][0] + R[1][1] * R[1][0];
|
||||||
A[1][1] = R[0][1]*R[0][1]+R[1][1]*R[1][1];
|
A[1][1] = R[0][1] * R[0][1] + R[1][1] * R[1][1];
|
||||||
A[1][2] = R[0][1]*R[0][2]+R[1][1]*R[1][2];
|
A[1][2] = R[0][1] * R[0][2] + R[1][1] * R[1][2];
|
||||||
|
|
||||||
A[2][0] = R[0][2]*R[0][0]+R[1][2]*R[1][0];
|
A[2][0] = R[0][2] * R[0][0] + R[1][2] * R[1][0];
|
||||||
A[2][1] = R[0][2]*R[0][1]+R[1][2]*R[1][1];
|
A[2][1] = R[0][2] * R[0][1] + R[1][2] * R[1][1];
|
||||||
A[2][2] = R[0][2]*R[0][2]+R[1][2]*R[1][2];
|
A[2][2] = R[0][2] * R[0][2] + R[1][2] * R[1][2];
|
||||||
|
|
||||||
/* vector B */
|
/* vector B */
|
||||||
P = Vector3(0.0, 0.0, 0.0);
|
P = Vector3(0.0, 0.0, 0.0);
|
||||||
B.x = -2.0*P.x; B.y = -2.0*P.y; B.z = -2.0*P.z;
|
B.x = -2.0 * P.x;
|
||||||
|
B.y = -2.0 * P.y;
|
||||||
|
B.z = -2.0 * P.z;
|
||||||
|
|
||||||
/* constant C */
|
/* constant C */
|
||||||
e0 = -2.0*(R[0][0]*P.x+R[0][1]*P.y+R[0][2]*P.z);
|
e0 = -2.0 * (R[0][0] * P.x + R[0][1] * P.y + R[0][2] * P.z);
|
||||||
e1 = -2.0*(R[1][0]*P.x+R[1][1]*P.y+R[1][2]*P.z);
|
e1 = -2.0 * (R[1][0] * P.x + R[1][1] * P.y + R[1][2] * P.z);
|
||||||
C = 0.25*(e0*e0+e1*e1) - radius*radius;
|
C = 0.25 * (e0 * e0 + e1 * e1) - radius * radius;
|
||||||
|
|
||||||
/* line */
|
/* line */
|
||||||
Q = ray.getOrigin().sub(axis.getOrigin());
|
Q = ray.getOrigin().sub(axis.getOrigin());
|
||||||
G = ray.getDirection();
|
G = ray.getDirection();
|
||||||
|
|
||||||
/* compute A*G */
|
/* compute A*G */
|
||||||
AG.x = A[0][0]*G.x+A[0][1]*G.y+A[0][2]*G.z;
|
AG.x = A[0][0] * G.x + A[0][1] * G.y + A[0][2] * G.z;
|
||||||
AG.y = A[1][0]*G.x+A[1][1]*G.y+A[1][2]*G.z;
|
AG.y = A[1][0] * G.x + A[1][1] * G.y + A[1][2] * G.z;
|
||||||
AG.z = A[2][0]*G.x+A[2][1]*G.y+A[2][2]*G.z;
|
AG.z = A[2][0] * G.x + A[2][1] * G.y + A[2][2] * G.z;
|
||||||
|
|
||||||
/* compute A*Q */
|
/* compute A*Q */
|
||||||
AQ.x = A[0][0]*Q.x+A[0][1]*Q.y+A[0][2]*Q.z;
|
AQ.x = A[0][0] * Q.x + A[0][1] * Q.y + A[0][2] * Q.z;
|
||||||
AQ.y = A[1][0]*Q.x+A[1][1]*Q.y+A[1][2]*Q.z;
|
AQ.y = A[1][0] * Q.x + A[1][1] * Q.y + A[1][2] * Q.z;
|
||||||
AQ.z = A[2][0]*Q.x+A[2][1]*Q.y+A[2][2]*Q.z;
|
AQ.z = A[2][0] * Q.x + A[2][1] * Q.y + A[2][2] * Q.z;
|
||||||
|
|
||||||
/* compute quadratic equation c0+c1*t+c2*t^2 = 0 */
|
/* compute quadratic equation c0+c1*t+c2*t^2 = 0 */
|
||||||
c2 = G.x*AG.x+G.y*AG.y+G.z*AG.z;
|
c2 = G.x * AG.x + G.y * AG.y + G.z * AG.z;
|
||||||
c1 = B.x*G.x+B.y*G.y+B.z*G.z+2.0f*(Q.x*AG.x+Q.y*AG.y+Q.z*AG.z);
|
c1 = B.x * G.x + B.y * G.y + B.z * G.z + 2.0f * (Q.x * AG.x + Q.y * AG.y + Q.z * AG.z);
|
||||||
c0 = Q.x*AQ.x+Q.y*AQ.y+Q.z*AQ.z+B.x*Q.x+B.y*Q.y+B.z*Q.z+C;
|
c0 = Q.x * AQ.x + Q.y * AQ.y + Q.z * AQ.z + B.x * Q.x + B.y * Q.y + B.z * Q.z + C;
|
||||||
|
|
||||||
/* solve for intersections */
|
/* solve for intersections */
|
||||||
int numIntersections;
|
int numIntersections;
|
||||||
discr = c1*c1-4.0*c0*c2;
|
discr = c1 * c1 - 4.0 * c0 * c2;
|
||||||
if ( discr > EPS )
|
if (discr > EPS) {
|
||||||
{
|
|
||||||
numIntersections = 2;
|
numIntersections = 2;
|
||||||
discr = sqrt(discr);
|
discr = sqrt(discr);
|
||||||
invC2 = 1.0/c2;
|
invC2 = 1.0 / c2;
|
||||||
root0 = -0.5*(c1+discr)*invC2;
|
root0 = -0.5 * (c1 + discr) * invC2;
|
||||||
root1 = -0.5*(c1-discr)*invC2;
|
root1 = -0.5 * (c1 - discr) * invC2;
|
||||||
first_intersection->x = Q.x+root0*G.x;
|
first_intersection->x = Q.x + root0 * G.x;
|
||||||
first_intersection->y = Q.y+root0*G.y;
|
first_intersection->y = Q.y + root0 * G.y;
|
||||||
first_intersection->z = Q.z+root0*G.z;
|
first_intersection->z = Q.z + root0 * G.z;
|
||||||
second_intersection->x = Q.x+root1*G.x;
|
second_intersection->x = Q.x + root1 * G.x;
|
||||||
second_intersection->y = Q.y+root1*G.y;
|
second_intersection->y = Q.y + root1 * G.y;
|
||||||
second_intersection->z = Q.z+root1*G.z;
|
second_intersection->z = Q.z + root1 * G.z;
|
||||||
|
|
||||||
*first_intersection = first_intersection->add(axis.getOrigin());
|
*first_intersection = first_intersection->add(axis.getOrigin());
|
||||||
*second_intersection = second_intersection->add(axis.getOrigin());
|
*second_intersection = second_intersection->add(axis.getOrigin());
|
||||||
}
|
} else if (discr < -EPS) {
|
||||||
else if ( discr < -EPS )
|
|
||||||
{
|
|
||||||
numIntersections = 0;
|
numIntersections = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
numIntersections = 1;
|
numIntersections = 1;
|
||||||
root = -0.5*c1/c2;
|
root = -0.5 * c1 / c2;
|
||||||
first_intersection->x = Q.x+root*G.x;
|
first_intersection->x = Q.x + root * G.x;
|
||||||
first_intersection->y = Q.y+root*G.y;
|
first_intersection->y = Q.y + root * G.y;
|
||||||
first_intersection->z = Q.z+root*G.z;
|
first_intersection->z = Q.z + root * G.z;
|
||||||
|
|
||||||
*first_intersection = first_intersection->add(axis.getOrigin());
|
*first_intersection = first_intersection->add(axis.getOrigin());
|
||||||
}
|
}
|
||||||
|
@ -136,14 +133,12 @@ int InfiniteCylinder::checkRayIntersection(const InfiniteRay &ray, Vector3 *firs
|
||||||
return numIntersections;
|
return numIntersections;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfiniteCylinder::save(PackStream *stream) const
|
void InfiniteCylinder::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
axis.save(stream);
|
axis.save(stream);
|
||||||
stream->write(&radius);
|
stream->write(&radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfiniteCylinder::load(PackStream *stream)
|
void InfiniteCylinder::load(PackStream *stream) {
|
||||||
{
|
|
||||||
axis.load(stream);
|
axis.load(stream);
|
||||||
stream->read(&radius);
|
stream->read(&radius);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,30 +11,32 @@ namespace basics {
|
||||||
/**
|
/**
|
||||||
* Geometric cylinder, with infinite length.
|
* Geometric cylinder, with infinite length.
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT InfiniteCylinder
|
class BASICSSHARED_EXPORT InfiniteCylinder {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
InfiniteCylinder();
|
InfiniteCylinder();
|
||||||
InfiniteCylinder(const InfiniteRay &axis, double radius);
|
InfiniteCylinder(const InfiniteRay &axis, double radius);
|
||||||
|
|
||||||
inline const InfiniteRay& getAxis() const {return axis;}
|
inline const InfiniteRay &getAxis() const {
|
||||||
inline double getRadius() const {return radius;}
|
return axis;
|
||||||
|
}
|
||||||
|
inline double getRadius() const {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the intersection between the cylinder and an infinite ray.
|
* Check the intersection between the cylinder and an infinite ray.
|
||||||
*
|
*
|
||||||
* Returns the number of intersections (0, 1 or 2) and fill the intersection points.
|
* Returns the number of intersections (0, 1 or 2) and fill the intersection points.
|
||||||
*/
|
*/
|
||||||
int checkRayIntersection(const InfiniteRay& ray, Vector3 *first_intersection, Vector3 *second_intersection) const;
|
int checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection, Vector3 *second_intersection) const;
|
||||||
|
|
||||||
virtual void save(PackStream *stream) const;
|
virtual void save(PackStream *stream) const;
|
||||||
virtual void load(PackStream *stream);
|
virtual void load(PackStream *stream);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
InfiniteRay axis;
|
InfiniteRay axis;
|
||||||
double radius;
|
double radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,28 +3,20 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "InfiniteRay.h"
|
#include "InfiniteRay.h"
|
||||||
|
|
||||||
InfinitePlane::InfinitePlane()
|
InfinitePlane::InfinitePlane() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InfinitePlane::InfinitePlane(const Vector3 &point, const Vector3 &normal):
|
InfinitePlane::InfinitePlane(const Vector3 &point, const Vector3 &normal) : point(point), normal(normal) {
|
||||||
point(point), normal(normal)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int InfinitePlane::checkRayIntersection(const InfiniteRay &ray, Vector3 *intersection) const
|
int InfinitePlane::checkRayIntersection(const InfiniteRay &ray, Vector3 *intersection) const {
|
||||||
{
|
|
||||||
Vector3 p1 = ray.getDirection();
|
Vector3 p1 = ray.getDirection();
|
||||||
double d = normal.dotProduct(p1);
|
double d = normal.dotProduct(p1);
|
||||||
|
|
||||||
if (fabs(d) < 1e-8)
|
if (fabs(d) < 1e-8) {
|
||||||
{
|
if (normal.dotProduct(ray.getPointAtCursor(1.0).sub(point)) == 0) {
|
||||||
if (normal.dotProduct(ray.getPointAtCursor(1.0).sub(point)) == 0)
|
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,15 +26,12 @@ int InfinitePlane::checkRayIntersection(const InfiniteRay &ray, Vector3 *interse
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfinitePlane::save(PackStream *stream) const
|
void InfinitePlane::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
point.save(stream);
|
point.save(stream);
|
||||||
normal.save(stream);
|
normal.save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfinitePlane::load(PackStream *stream)
|
void InfinitePlane::load(PackStream *stream) {
|
||||||
{
|
|
||||||
point.load(stream);
|
point.load(stream);
|
||||||
normal.load(stream);
|
normal.load(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,8 @@ namespace basics {
|
||||||
/**
|
/**
|
||||||
* Infinite 3d geometric plane.
|
* Infinite 3d geometric plane.
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT InfinitePlane
|
class BASICSSHARED_EXPORT InfinitePlane {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
InfinitePlane();
|
InfinitePlane();
|
||||||
InfinitePlane(const Vector3 &point, const Vector3 &normal);
|
InfinitePlane(const Vector3 &point, const Vector3 &normal);
|
||||||
|
|
||||||
|
@ -24,19 +23,22 @@ public:
|
||||||
*
|
*
|
||||||
* Returns -1 if the ray is on the plane, and make for an infinite number of intersection points.
|
* Returns -1 if the ray is on the plane, and make for an infinite number of intersection points.
|
||||||
*/
|
*/
|
||||||
int checkRayIntersection(const InfiniteRay& ray, Vector3 *intersection) const;
|
int checkRayIntersection(const InfiniteRay &ray, Vector3 *intersection) const;
|
||||||
|
|
||||||
inline const Vector3 &getPoint() const {return point;}
|
inline const Vector3 &getPoint() const {
|
||||||
inline const Vector3 &getNormal() const {return normal;}
|
return point;
|
||||||
|
}
|
||||||
|
inline const Vector3 &getNormal() const {
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void save(PackStream *stream) const;
|
virtual void save(PackStream *stream) const;
|
||||||
virtual void load(PackStream *stream);
|
virtual void load(PackStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 point;
|
Vector3 point;
|
||||||
Vector3 normal;
|
Vector3 normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,22 @@
|
||||||
#include "InfiniteRay.h"
|
#include "InfiniteRay.h"
|
||||||
|
|
||||||
InfiniteRay::InfiniteRay()
|
InfiniteRay::InfiniteRay() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InfiniteRay::InfiniteRay(const Vector3 &origin, const Vector3 &direction):
|
InfiniteRay::InfiniteRay(const Vector3 &origin, const Vector3 &direction)
|
||||||
origin(origin), direction(direction.normalize())
|
: origin(origin), direction(direction.normalize()) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InfiniteRay InfiniteRay::fromPoints(const Vector3 &point1, const Vector3 &point2)
|
InfiniteRay InfiniteRay::fromPoints(const Vector3 &point1, const Vector3 &point2) {
|
||||||
{
|
|
||||||
return InfiniteRay(point1, point2.sub(point1).normalize());
|
return InfiniteRay(point1, point2.sub(point1).normalize());
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfiniteRay::save(PackStream *stream) const
|
void InfiniteRay::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
origin.save(stream);
|
origin.save(stream);
|
||||||
direction.save(stream);
|
direction.save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfiniteRay::load(PackStream *stream)
|
void InfiniteRay::load(PackStream *stream) {
|
||||||
{
|
|
||||||
origin.load(stream);
|
origin.load(stream);
|
||||||
direction.load(stream);
|
direction.load(stream);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,28 +11,34 @@ namespace basics {
|
||||||
/**
|
/**
|
||||||
* Infinite ray (line).
|
* Infinite ray (line).
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT InfiniteRay
|
class BASICSSHARED_EXPORT InfiniteRay {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
InfiniteRay();
|
InfiniteRay();
|
||||||
InfiniteRay(const Vector3 &origin, const Vector3 &direction);
|
InfiniteRay(const Vector3 &origin, const Vector3 &direction);
|
||||||
|
|
||||||
static InfiniteRay fromPoints(const Vector3 &point1, const Vector3 &point2);
|
static InfiniteRay fromPoints(const Vector3 &point1, const Vector3 &point2);
|
||||||
|
|
||||||
inline const Vector3 &getOrigin() const {return origin;}
|
inline const Vector3 &getOrigin() const {
|
||||||
inline const Vector3 &getDirection() const {return direction;}
|
return origin;
|
||||||
|
}
|
||||||
|
inline const Vector3 &getDirection() const {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
inline double getCursor(const Vector3 &point) const {return point.sub(origin).dotProduct(direction);}
|
inline double getCursor(const Vector3 &point) const {
|
||||||
inline Vector3 getPointAtCursor(double distance) const {return origin.add(direction.scale(distance));}
|
return point.sub(origin).dotProduct(direction);
|
||||||
|
}
|
||||||
|
inline Vector3 getPointAtCursor(double distance) const {
|
||||||
|
return origin.add(direction.scale(distance));
|
||||||
|
}
|
||||||
|
|
||||||
void save(PackStream *stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream *stream);
|
void load(PackStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 origin;
|
Vector3 origin;
|
||||||
Vector3 direction;
|
Vector3 direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "Interpolation.h"
|
#include "Interpolation.h"
|
||||||
|
|
||||||
double Interpolation::bicubic(double stencil[16], double x, double y)
|
double Interpolation::bicubic(double stencil[16], double x, double y) {
|
||||||
{
|
|
||||||
double buf_cubic_y[4];
|
double buf_cubic_y[4];
|
||||||
|
|
||||||
buf_cubic_y[0] = Interpolation::cubic(stencil, x);
|
buf_cubic_y[0] = Interpolation::cubic(stencil, x);
|
||||||
|
@ -12,15 +11,13 @@ double Interpolation::bicubic(double stencil[16], double x, double y)
|
||||||
return Interpolation::cubic(buf_cubic_y, y);
|
return Interpolation::cubic(buf_cubic_y, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Interpolation::bilinear(double p[4], double x, double y)
|
double Interpolation::bilinear(double p[4], double x, double y) {
|
||||||
{
|
|
||||||
double e1 = linear(p[0], p[1], x);
|
double e1 = linear(p[0], p[1], x);
|
||||||
double e2 = linear(p[3], p[2], x);
|
double e2 = linear(p[3], p[2], x);
|
||||||
return Interpolation::linear(e1, e2, y);
|
return Interpolation::linear(e1, e2, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Interpolation::trilinear(double p[8], double x, double y, double z)
|
double Interpolation::trilinear(double p[8], double x, double y, double z) {
|
||||||
{
|
|
||||||
double f1 = bilinear(p, x, y);
|
double f1 = bilinear(p, x, y);
|
||||||
double f2 = bilinear(p + 4, x, y);
|
double f2 = bilinear(p + 4, x, y);
|
||||||
return Interpolation::linear(f1, f2, z);
|
return Interpolation::linear(f1, f2, z);
|
||||||
|
|
|
@ -6,23 +6,21 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Interpolation
|
class BASICSSHARED_EXPORT Interpolation {
|
||||||
{
|
public:
|
||||||
public:
|
static inline double linear(double p1, double p2, double x) {
|
||||||
static inline double linear(double p1, double p2, double x)
|
|
||||||
{
|
|
||||||
return p1 + x * (p2 - p1);
|
return p1 + x * (p2 - p1);
|
||||||
}
|
}
|
||||||
static double bilinear(double p[4], double x, double y);
|
static double bilinear(double p[4], double x, double y);
|
||||||
static double trilinear(double p[8], double x, double y, double z);
|
static double trilinear(double p[8], double x, double y, double z);
|
||||||
|
|
||||||
static inline double cubic(double p[4], double x)
|
static inline double cubic(double p[4], double x) {
|
||||||
{
|
return p[1] +
|
||||||
return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
|
0.5 * x * (p[2] - p[0] +
|
||||||
|
x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
|
||||||
}
|
}
|
||||||
static double bicubic(double stencil[16], double x, double y);
|
static double bicubic(double stencil[16], double x, double y);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,13 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
|
||||||
Matrix4::Matrix4(bool identity)
|
Matrix4::Matrix4(bool identity) {
|
||||||
{
|
|
||||||
b = c = d = e = g = h = 0.0;
|
b = c = d = e = g = h = 0.0;
|
||||||
i = j = l = m = n = o = 0.0;
|
i = j = l = m = n = o = 0.0;
|
||||||
a = f = k = p = (identity ? 1.0 : 0.0);
|
a = f = k = p = (identity ? 1.0 : 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix4::save(PackStream* stream) const
|
void Matrix4::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
stream->write(&a);
|
stream->write(&a);
|
||||||
stream->write(&b);
|
stream->write(&b);
|
||||||
stream->write(&c);
|
stream->write(&c);
|
||||||
|
@ -31,8 +29,7 @@ void Matrix4::save(PackStream* stream) const
|
||||||
stream->write(&p);
|
stream->write(&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix4::load(PackStream* stream)
|
void Matrix4::load(PackStream *stream) {
|
||||||
{
|
|
||||||
stream->read(&a);
|
stream->read(&a);
|
||||||
stream->read(&b);
|
stream->read(&b);
|
||||||
stream->read(&c);
|
stream->read(&c);
|
||||||
|
@ -51,8 +48,7 @@ void Matrix4::load(PackStream* stream)
|
||||||
stream->read(&p);
|
stream->read(&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::mult(const Matrix4 &other) const
|
Matrix4 Matrix4::mult(const Matrix4 &other) const {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
result.a = a * other.a + b * other.e + c * other.i + d * other.m;
|
result.a = a * other.a + b * other.e + c * other.i + d * other.m;
|
||||||
result.b = a * other.b + b * other.f + c * other.j + d * other.n;
|
result.b = a * other.b + b * other.f + c * other.j + d * other.n;
|
||||||
|
@ -73,8 +69,7 @@ Matrix4 Matrix4::mult(const Matrix4 &other) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Matrix4::multPoint(const Vector3 &v) const
|
Vector3 Matrix4::multPoint(const Vector3 &v) const {
|
||||||
{
|
|
||||||
Vector3 result;
|
Vector3 result;
|
||||||
result.x = a * v.x + b * v.y + c * v.z + d;
|
result.x = a * v.x + b * v.y + c * v.z + d;
|
||||||
result.y = e * v.x + f * v.y + g * v.z + h;
|
result.y = e * v.x + f * v.y + g * v.z + h;
|
||||||
|
@ -82,30 +77,19 @@ Vector3 Matrix4::multPoint(const Vector3 &v) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Matrix4::transform(const Vector3 &v) const
|
Vector3 Matrix4::transform(const Vector3 &v) const {
|
||||||
{
|
|
||||||
double w = m * v.x + n * v.y + o * v.z + p;
|
double w = m * v.x + n * v.y + o * v.z + p;
|
||||||
if (w != 0.0)
|
if (w != 0.0) {
|
||||||
{
|
|
||||||
w = 1.0 / w;
|
w = 1.0 / w;
|
||||||
return Vector3(
|
return Vector3((a * v.x + b * v.y + c * v.z + d) * w, (e * v.x + f * v.y + g * v.z + h) * w,
|
||||||
(a * v.x + b * v.y + c * v.z + d) * w,
|
(i * v.x + j * v.y + k * v.z + l) * w);
|
||||||
(e * v.x + f * v.y + g * v.z + h) * w,
|
} else {
|
||||||
(i * v.x + j * v.y + k * v.z + l) * w
|
return Vector3(a * v.x + b * v.y + c * v.z + d, e * v.x + f * v.y + g * v.z + h,
|
||||||
);
|
i * v.x + j * v.y + k * v.z + l);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Vector3(
|
|
||||||
a * v.x + b * v.y + c * v.z + d,
|
|
||||||
e * v.x + f * v.y + g * v.z + h,
|
|
||||||
i * v.x + j * v.y + k * v.z + l
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::transposed() const
|
Matrix4 Matrix4::transposed() const {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
result.a = a;
|
result.a = a;
|
||||||
result.e = b;
|
result.e = b;
|
||||||
|
@ -126,8 +110,7 @@ Matrix4 Matrix4::transposed() const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newScale(double x, double y, double z)
|
Matrix4 Matrix4::newScale(double x, double y, double z) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
result.a = x;
|
result.a = x;
|
||||||
result.f = y;
|
result.f = y;
|
||||||
|
@ -135,8 +118,7 @@ Matrix4 Matrix4::newScale(double x, double y, double z)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newTranslate(double x, double y, double z)
|
Matrix4 Matrix4::newTranslate(double x, double y, double z) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
result.d = x;
|
result.d = x;
|
||||||
result.h = y;
|
result.h = y;
|
||||||
|
@ -144,8 +126,7 @@ Matrix4 Matrix4::newTranslate(double x, double y, double z)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newRotateX(double angle)
|
Matrix4 Matrix4::newRotateX(double angle) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
double si = sin(angle);
|
double si = sin(angle);
|
||||||
double co = cos(angle);
|
double co = cos(angle);
|
||||||
|
@ -155,8 +136,7 @@ Matrix4 Matrix4::newRotateX(double angle)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newRotateY(double angle)
|
Matrix4 Matrix4::newRotateY(double angle) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
double si = sin(angle);
|
double si = sin(angle);
|
||||||
double co = cos(angle);
|
double co = cos(angle);
|
||||||
|
@ -166,8 +146,7 @@ Matrix4 Matrix4::newRotateY(double angle)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newRotateZ(double angle)
|
Matrix4 Matrix4::newRotateZ(double angle) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
double si = sin(angle);
|
double si = sin(angle);
|
||||||
double co = cos(angle);
|
double co = cos(angle);
|
||||||
|
@ -177,8 +156,7 @@ Matrix4 Matrix4::newRotateZ(double angle)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newRotateAxis(double angle, const Vector3 &_axis)
|
Matrix4 Matrix4::newRotateAxis(double angle, const Vector3 &_axis) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
double si = sin(angle);
|
double si = sin(angle);
|
||||||
double co = cos(angle);
|
double co = cos(angle);
|
||||||
|
@ -196,8 +174,7 @@ Matrix4 Matrix4::newRotateAxis(double angle, const Vector3 &_axis)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newRotateEuler(double heading, double attitude, double bank)
|
Matrix4 Matrix4::newRotateEuler(double heading, double attitude, double bank) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
double ch = cos(heading);
|
double ch = cos(heading);
|
||||||
double sh = sin(heading);
|
double sh = sin(heading);
|
||||||
|
@ -217,8 +194,7 @@ Matrix4 Matrix4::newRotateEuler(double heading, double attitude, double bank)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newRotateTripleAxis(const Vector3 &x, const Vector3 &y, const Vector3 &z)
|
Matrix4 Matrix4::newRotateTripleAxis(const Vector3 &x, const Vector3 &y, const Vector3 &z) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
result.a = x.x;
|
result.a = x.x;
|
||||||
result.b = y.x;
|
result.b = y.x;
|
||||||
|
@ -232,8 +208,7 @@ Matrix4 Matrix4::newRotateTripleAxis(const Vector3 &x, const Vector3 &y, const V
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newLookAt(const Vector3 &eye, const Vector3 &at, const Vector3 &up)
|
Matrix4 Matrix4::newLookAt(const Vector3 &eye, const Vector3 &at, const Vector3 &up) {
|
||||||
{
|
|
||||||
Vector3 z = at.sub(eye).normalize();
|
Vector3 z = at.sub(eye).normalize();
|
||||||
Vector3 x = up.crossProduct(z).normalize();
|
Vector3 x = up.crossProduct(z).normalize();
|
||||||
Vector3 y = z.crossProduct(x);
|
Vector3 y = z.crossProduct(x);
|
||||||
|
@ -244,8 +219,7 @@ Matrix4 Matrix4::newLookAt(const Vector3 &eye, const Vector3 &at, const Vector3
|
||||||
return result.inversed();
|
return result.inversed();
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::newPerspective(double fov_y, double aspect, double near, double far)
|
Matrix4 Matrix4::newPerspective(double fov_y, double aspect, double near, double far) {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
double fo = 1 / tan(fov_y / 2.0);
|
double fo = 1 / tan(fov_y / 2.0);
|
||||||
result.a = fo / aspect;
|
result.a = fo / aspect;
|
||||||
|
@ -257,29 +231,16 @@ Matrix4 Matrix4::newPerspective(double fov_y, double aspect, double near, double
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Matrix4::getDeterminant() const
|
double Matrix4::getDeterminant() const {
|
||||||
{
|
return ((a * f - e * b) * (k * p - o * l) - (a * j - i * b) * (g * p - o * h) + (a * n - m * b) * (g * l - k * h) +
|
||||||
return ((a * f - e * b)
|
(e * j - i * f) * (c * p - o * d) - (e * n - m * f) * (c * l - k * d) + (i * n - m * j) * (c * h - g * d));
|
||||||
* (k * p - o * l)
|
|
||||||
- (a * j - i * b)
|
|
||||||
* (g * p - o * h)
|
|
||||||
+ (a * n - m * b)
|
|
||||||
* (g * l - k * h)
|
|
||||||
+ (e * j - i * f)
|
|
||||||
* (c * p - o * d)
|
|
||||||
- (e * n - m * f)
|
|
||||||
* (c * l - k * d)
|
|
||||||
+ (i * n - m * j)
|
|
||||||
* (c * h - g * d));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 Matrix4::inversed() const
|
Matrix4 Matrix4::inversed() const {
|
||||||
{
|
|
||||||
Matrix4 result;
|
Matrix4 result;
|
||||||
double det = getDeterminant();
|
double det = getDeterminant();
|
||||||
|
|
||||||
if (fabs(det) >= 0.00001)
|
if (fabs(det) >= 0.00001) {
|
||||||
{
|
|
||||||
det = 1.0 / det;
|
det = 1.0 / det;
|
||||||
|
|
||||||
result.a = det * (f * (k * p - o * l) + j * (o * h - g * p) + n * (g * l - k * h));
|
result.a = det * (f * (k * p - o * l) + j * (o * h - g * p) + n * (g * l - k * h));
|
||||||
|
@ -301,7 +262,6 @@ Matrix4 Matrix4::inversed() const
|
||||||
result.h = det * (c * (i * h - e * l) + g * (a * l - i * d) + k * (e * d - a * h));
|
result.h = det * (c * (i * h - e * l) + g * (a * l - i * d) + k * (e * d - a * h));
|
||||||
result.l = det * (d * (i * f - e * j) + h * (a * j - i * b) + l * (e * b - a * f));
|
result.l = det * (d * (i * f - e * j) + h * (a * j - i * b) + l * (e * b - a * f));
|
||||||
result.p = det * (a * (f * k - j * g) + e * (j * c - b * k) + i * (b * g - f * c));
|
result.p = det * (a * (f * k - j * g) + e * (j * c - b * k) + i * (b * g - f * c));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -10,13 +10,12 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Matrix4
|
class BASICSSHARED_EXPORT Matrix4 {
|
||||||
{
|
public:
|
||||||
public:
|
Matrix4(bool identity = true);
|
||||||
Matrix4(bool identity=true);
|
|
||||||
|
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
|
|
||||||
Matrix4 mult(const Matrix4 &other) const;
|
Matrix4 mult(const Matrix4 &other) const;
|
||||||
Vector3 multPoint(const Vector3 &v) const;
|
Vector3 multPoint(const Vector3 &v) const;
|
||||||
|
@ -39,14 +38,11 @@ public:
|
||||||
|
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
inline QMatrix4x4 toQMatrix() const {
|
inline QMatrix4x4 toQMatrix() const {
|
||||||
return QMatrix4x4(a, b, c, d,
|
return QMatrix4x4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
|
||||||
e, f, g, h,
|
|
||||||
i, j, k, l,
|
|
||||||
m, n, o, p);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double a;
|
double a;
|
||||||
double b;
|
double b;
|
||||||
double c;
|
double c;
|
||||||
|
@ -64,7 +60,6 @@ private:
|
||||||
double o;
|
double o;
|
||||||
double p;
|
double p;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
NoiseFunctionPerlin::NoiseFunctionPerlin()
|
NoiseFunctionPerlin::NoiseFunctionPerlin() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define B 0x100
|
#define B 0x100
|
||||||
|
@ -25,108 +24,117 @@ static double g3[B + B + 2][3];
|
||||||
static double g2[B + B + 2][2];
|
static double g2[B + B + 2][2];
|
||||||
static double g1[B + B + 2];
|
static double g1[B + B + 2];
|
||||||
|
|
||||||
#define s_curve(t) ( t * t * (3. - 2. * t) )
|
#define s_curve(t) (t * t * (3. - 2. * t))
|
||||||
|
|
||||||
#define lerp(t, a, b) ( a + t * (b - a) )
|
#define lerp(t, a, b) (a + t * (b - a))
|
||||||
|
|
||||||
#define setup(i,b0,b1,r0,r1)\
|
#define setup(i, b0, b1, r0, r1) \
|
||||||
t = vec[i] + N;\
|
t = vec[i] + N; \
|
||||||
b0 = ((int)t) & BM;\
|
b0 = ((int)t) & BM; \
|
||||||
b1 = (b0+1) & BM;\
|
b1 = (b0 + 1) & BM; \
|
||||||
r0 = t - (int)t;\
|
r0 = t - (int)t; \
|
||||||
r1 = r0 - 1.;
|
r1 = r0 - 1.;
|
||||||
|
|
||||||
double noisePerlinGet1DValue(double x)
|
double noisePerlinGet1DValue(double x) {
|
||||||
{
|
double vec[1] = {x * 2.0};
|
||||||
double vec[1] = {x*2.0};
|
|
||||||
int bx0, bx1;
|
int bx0, bx1;
|
||||||
double rx0, rx1, sx, t, u, v;
|
double rx0, rx1, sx, t, u, v;
|
||||||
|
|
||||||
setup(0, bx0,bx1, rx0,rx1);
|
setup(0, bx0, bx1, rx0, rx1);
|
||||||
|
|
||||||
sx = s_curve(rx0);
|
sx = s_curve(rx0);
|
||||||
|
|
||||||
u = rx0 * g1[ p[ bx0 ] ];
|
u = rx0 * g1[p[bx0]];
|
||||||
v = rx1 * g1[ p[ bx1 ] ];
|
v = rx1 * g1[p[bx1]];
|
||||||
|
|
||||||
return lerp(sx, u, v) * 1.068 + 0.5;
|
return lerp(sx, u, v) * 1.068 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
double noisePerlinGet2DValue(double x, double y)
|
double noisePerlinGet2DValue(double x, double y) {
|
||||||
{
|
double vec[2] = {x * 2.0, y * 2.0};
|
||||||
double vec[2] = {x*2.0, y*2.0};
|
|
||||||
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
||||||
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
setup(0, bx0,bx1, rx0,rx1);
|
setup(0, bx0, bx1, rx0, rx1);
|
||||||
setup(1, by0,by1, ry0,ry1);
|
setup(1, by0, by1, ry0, ry1);
|
||||||
|
|
||||||
i = p[ bx0 ];
|
i = p[bx0];
|
||||||
j = p[ bx1 ];
|
j = p[bx1];
|
||||||
|
|
||||||
b00 = p[ i + by0 ];
|
b00 = p[i + by0];
|
||||||
b10 = p[ j + by0 ];
|
b10 = p[j + by0];
|
||||||
b01 = p[ i + by1 ];
|
b01 = p[i + by1];
|
||||||
b11 = p[ j + by1 ];
|
b11 = p[j + by1];
|
||||||
|
|
||||||
sx = s_curve(rx0);
|
sx = s_curve(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = s_curve(ry0);
|
||||||
|
|
||||||
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
|
#define at2(rx, ry) (rx * q[0] + ry * q[1])
|
||||||
|
|
||||||
q = g2[ b00 ] ; u = at2(rx0,ry0);
|
q = g2[b00];
|
||||||
q = g2[ b10 ] ; v = at2(rx1,ry0);
|
u = at2(rx0, ry0);
|
||||||
|
q = g2[b10];
|
||||||
|
v = at2(rx1, ry0);
|
||||||
a = lerp(sx, u, v);
|
a = lerp(sx, u, v);
|
||||||
|
|
||||||
q = g2[ b01 ] ; u = at2(rx0,ry1);
|
q = g2[b01];
|
||||||
q = g2[ b11 ] ; v = at2(rx1,ry1);
|
u = at2(rx0, ry1);
|
||||||
|
q = g2[b11];
|
||||||
|
v = at2(rx1, ry1);
|
||||||
b = lerp(sx, u, v);
|
b = lerp(sx, u, v);
|
||||||
|
|
||||||
return lerp(sy, a, b) * 0.709 + 0.5;
|
return lerp(sy, a, b) * 0.709 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
double noisePerlinGet3DValue(double x, double y, double z)
|
double noisePerlinGet3DValue(double x, double y, double z) {
|
||||||
{
|
double vec[3] = {x * 2.0, y * 2.0, z * 2.0};
|
||||||
double vec[3] = {x*2.0, y*2.0, z*2.0};
|
|
||||||
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
||||||
double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
setup(0, bx0,bx1, rx0,rx1);
|
setup(0, bx0, bx1, rx0, rx1);
|
||||||
setup(1, by0,by1, ry0,ry1);
|
setup(1, by0, by1, ry0, ry1);
|
||||||
setup(2, bz0,bz1, rz0,rz1);
|
setup(2, bz0, bz1, rz0, rz1);
|
||||||
|
|
||||||
i = p[ bx0 ];
|
i = p[bx0];
|
||||||
j = p[ bx1 ];
|
j = p[bx1];
|
||||||
|
|
||||||
b00 = p[ i + by0 ];
|
b00 = p[i + by0];
|
||||||
b10 = p[ j + by0 ];
|
b10 = p[j + by0];
|
||||||
b01 = p[ i + by1 ];
|
b01 = p[i + by1];
|
||||||
b11 = p[ j + by1 ];
|
b11 = p[j + by1];
|
||||||
|
|
||||||
t = s_curve(rx0);
|
t = s_curve(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = s_curve(ry0);
|
||||||
sz = s_curve(rz0);
|
sz = s_curve(rz0);
|
||||||
|
|
||||||
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
#define at3(rx, ry, rz) (rx * q[0] + ry * q[1] + rz * q[2])
|
||||||
|
|
||||||
q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
|
q = g3[b00 + bz0];
|
||||||
q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
|
u = at3(rx0, ry0, rz0);
|
||||||
|
q = g3[b10 + bz0];
|
||||||
|
v = at3(rx1, ry0, rz0);
|
||||||
a = lerp(t, u, v);
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
|
q = g3[b01 + bz0];
|
||||||
q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
|
u = at3(rx0, ry1, rz0);
|
||||||
|
q = g3[b11 + bz0];
|
||||||
|
v = at3(rx1, ry1, rz0);
|
||||||
b = lerp(t, u, v);
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
c = lerp(sy, a, b);
|
c = lerp(sy, a, b);
|
||||||
|
|
||||||
q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
|
q = g3[b00 + bz1];
|
||||||
q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
|
u = at3(rx0, ry0, rz1);
|
||||||
|
q = g3[b10 + bz1];
|
||||||
|
v = at3(rx1, ry0, rz1);
|
||||||
a = lerp(t, u, v);
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
|
q = g3[b01 + bz1];
|
||||||
q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
|
u = at3(rx0, ry1, rz1);
|
||||||
|
q = g3[b11 + bz1];
|
||||||
|
v = at3(rx1, ry1, rz1);
|
||||||
b = lerp(t, u, v);
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
d = lerp(sy, a, b);
|
d = lerp(sy, a, b);
|
||||||
|
@ -134,8 +142,7 @@ double noisePerlinGet3DValue(double x, double y, double z)
|
||||||
return lerp(sz, c, d) * 0.661 + 0.5;
|
return lerp(sz, c, d) * 0.661 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _normalize2(double v[2])
|
static void _normalize2(double v[2]) {
|
||||||
{
|
|
||||||
double s;
|
double s;
|
||||||
|
|
||||||
s = sqrt(v[0] * v[0] + v[1] * v[1]);
|
s = sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||||
|
@ -143,8 +150,7 @@ static void _normalize2(double v[2])
|
||||||
v[1] = v[1] / s;
|
v[1] = v[1] / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _normalize3(double v[3])
|
static void _normalize3(double v[3]) {
|
||||||
{
|
|
||||||
double s;
|
double s;
|
||||||
|
|
||||||
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
|
@ -153,20 +159,19 @@ static void _normalize3(double v[3])
|
||||||
v[2] = v[2] / s;
|
v[2] = v[2] / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int noisePerlinInit(void)
|
static int noisePerlinInit(void) {
|
||||||
{
|
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
for (i = 0 ; i < B ; i++) {
|
for (i = 0; i < B; i++) {
|
||||||
p[i] = i;
|
p[i] = i;
|
||||||
|
|
||||||
g1[i] = (double)((rand() % (B + B)) - B) / B;
|
g1[i] = (double)((rand() % (B + B)) - B) / B;
|
||||||
|
|
||||||
for (j = 0 ; j < 2 ; j++)
|
for (j = 0; j < 2; j++)
|
||||||
g2[i][j] = (double)((rand() % (B + B)) - B) / B;
|
g2[i][j] = (double)((rand() % (B + B)) - B) / B;
|
||||||
_normalize2(g2[i]);
|
_normalize2(g2[i]);
|
||||||
|
|
||||||
for (j = 0 ; j < 3 ; j++)
|
for (j = 0; j < 3; j++)
|
||||||
g3[i][j] = (double)((rand() % (B + B)) - B) / B;
|
g3[i][j] = (double)((rand() % (B + B)) - B) / B;
|
||||||
_normalize3(g3[i]);
|
_normalize3(g3[i]);
|
||||||
}
|
}
|
||||||
|
@ -177,12 +182,12 @@ static int noisePerlinInit(void)
|
||||||
p[j] = k;
|
p[j] = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0 ; i < B + 2 ; i++) {
|
for (i = 0; i < B + 2; i++) {
|
||||||
p[B + i] = p[i];
|
p[B + i] = p[i];
|
||||||
g1[B + i] = g1[i];
|
g1[B + i] = g1[i];
|
||||||
for (j = 0 ; j < 2 ; j++)
|
for (j = 0; j < 2; j++)
|
||||||
g2[B + i][j] = g2[i][j];
|
g2[B + i][j] = g2[i][j];
|
||||||
for (j = 0 ; j < 3 ; j++)
|
for (j = 0; j < 3; j++)
|
||||||
g3[B + i][j] = g3[i][j];
|
g3[B + i][j] = g3[i][j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,10 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class NoiseFunctionPerlin
|
class NoiseFunctionPerlin {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
NoiseFunctionPerlin();
|
NoiseFunctionPerlin();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,23 +14,20 @@
|
||||||
#include "Geometry.h"
|
#include "Geometry.h"
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
double z;
|
double z;
|
||||||
} Grad3;
|
} Grad3;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
double z;
|
double z;
|
||||||
double w;
|
double w;
|
||||||
} Grad4;
|
} Grad4;
|
||||||
|
|
||||||
static Grad3 _grad3[] = {
|
static Grad3 _grad3[] = {{1, 1, 0},
|
||||||
{1, 1, 0},
|
|
||||||
{-1, 1, 0},
|
{-1, 1, 0},
|
||||||
{1, -1, 0},
|
{1, -1, 0},
|
||||||
{-1, -1, 0},
|
{-1, -1, 0},
|
||||||
|
@ -41,11 +38,9 @@ static Grad3 _grad3[] = {
|
||||||
{0, 1, 1},
|
{0, 1, 1},
|
||||||
{0, -1, 1},
|
{0, -1, 1},
|
||||||
{0, 1, -1},
|
{0, 1, -1},
|
||||||
{0, -1, -1}
|
{0, -1, -1}};
|
||||||
};
|
|
||||||
|
|
||||||
static Grad4 _grad4[] = {
|
static Grad4 _grad4[] = {{0, 1, 1, 1},
|
||||||
{0, 1, 1, 1},
|
|
||||||
{0, 1, 1, -1},
|
{0, 1, 1, -1},
|
||||||
{0, 1, -1, 1},
|
{0, 1, -1, 1},
|
||||||
{0, 1, -1, -1},
|
{0, 1, -1, -1},
|
||||||
|
@ -76,22 +71,21 @@ static Grad4 _grad4[] = {
|
||||||
{-1, 1, 1, 0},
|
{-1, 1, 1, 0},
|
||||||
{-1, 1, -1, 0},
|
{-1, 1, -1, 0},
|
||||||
{-1, -1, 1, 0},
|
{-1, -1, 1, 0},
|
||||||
{-1, -1, -1, 0}
|
{-1, -1, -1, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
static short _permutations[] = {151, 160, 137, 91, 90, 15,
|
static short _permutations[] = {
|
||||||
131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
|
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142,
|
||||||
190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
|
8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203,
|
||||||
88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
|
117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165,
|
||||||
77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
|
71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41,
|
||||||
102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
|
55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89,
|
||||||
135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
|
18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250,
|
||||||
5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
|
124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189,
|
||||||
223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
|
28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
|
||||||
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
|
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34,
|
||||||
251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
|
242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31,
|
||||||
49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
|
181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114,
|
||||||
138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180};
|
67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180};
|
||||||
static short _permutations2[512];
|
static short _permutations2[512];
|
||||||
static short _permutationsMod12[512];
|
static short _permutationsMod12[512];
|
||||||
|
|
||||||
|
@ -102,36 +96,30 @@ static double _G3;
|
||||||
static double _F4;
|
static double _F4;
|
||||||
static double _G4;
|
static double _G4;
|
||||||
|
|
||||||
static inline int _fastfloor(double x)
|
static inline int _fastfloor(double x) {
|
||||||
{
|
int xi = (int)x;
|
||||||
int xi = (int) x;
|
|
||||||
return x < xi ? xi - 1 : xi;
|
return x < xi ? xi - 1 : xi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double _dot2(Grad3 g, double x, double y)
|
static inline double _dot2(Grad3 g, double x, double y) {
|
||||||
{
|
|
||||||
return g.x * x + g.y * y;
|
return g.x * x + g.y * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double _dot3(Grad3 g, double x, double y, double z)
|
static inline double _dot3(Grad3 g, double x, double y, double z) {
|
||||||
{
|
|
||||||
return g.x * x + g.y * y + g.z * z;
|
return g.x * x + g.y * y + g.z * z;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double _dot4(Grad4 g, double x, double y, double z, double w)
|
static inline double _dot4(Grad4 g, double x, double y, double z, double w) {
|
||||||
{
|
|
||||||
return g.x * x + g.y * y + g.z * z + g.w * w;
|
return g.x * x + g.y * y + g.z * z + g.w * w;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int noiseSimplexInit()
|
static int noiseSimplexInit() {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* To remove the need for index wrapping, double the permutation table length */
|
/* To remove the need for index wrapping, double the permutation table length */
|
||||||
for (i = 0; i < 512; i++)
|
for (i = 0; i < 512; i++) {
|
||||||
{
|
|
||||||
_permutations2[i] = _permutations[i & 255];
|
_permutations2[i] = _permutations[i & 255];
|
||||||
_permutationsMod12[i] = (short) (_permutations2[i] % 12);
|
_permutationsMod12[i] = (short)(_permutations2[i] % 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skewing and unskewing factors for 2, 3, and 4 dimensions */
|
/* Skewing and unskewing factors for 2, 3, and 4 dimensions */
|
||||||
|
@ -147,14 +135,12 @@ static int noiseSimplexInit()
|
||||||
|
|
||||||
static int _inited = noiseSimplexInit();
|
static int _inited = noiseSimplexInit();
|
||||||
|
|
||||||
double noiseSimplexGet1DValue(double x)
|
double noiseSimplexGet1DValue(double x) {
|
||||||
{
|
|
||||||
/* TODO Find custom function */
|
/* TODO Find custom function */
|
||||||
return noiseSimplexGet2DValue(x, 0.0);
|
return noiseSimplexGet2DValue(x, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double noiseSimplexGet2DValue(double x, double y)
|
double noiseSimplexGet2DValue(double x, double y) {
|
||||||
{
|
|
||||||
double n0, n1, n2; /* Noise contributions from the three corners */
|
double n0, n1, n2; /* Noise contributions from the three corners */
|
||||||
/* Skew the input space to determine which simplex cell we're in */
|
/* Skew the input space to determine which simplex cell we're in */
|
||||||
double s = (x + y) * _F2; /* Hairy factor for 2D */
|
double s = (x + y) * _F2; /* Hairy factor for 2D */
|
||||||
|
@ -168,13 +154,11 @@ double noiseSimplexGet2DValue(double x, double y)
|
||||||
/* For the 2D case, the simplex shape is an equilateral triangle.
|
/* For the 2D case, the simplex shape is an equilateral triangle.
|
||||||
Determine which simplex we are in. */
|
Determine which simplex we are in. */
|
||||||
int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */
|
int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */
|
||||||
if (x0 > y0)
|
if (x0 > y0) {
|
||||||
{
|
|
||||||
i1 = 1;
|
i1 = 1;
|
||||||
j1 = 0;
|
j1 = 0;
|
||||||
} /* lower triangle, XY order: (0,0)->(1,0)->(1,1) */
|
} /* lower triangle, XY order: (0,0)->(1,0)->(1,1) */
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
i1 = 0;
|
i1 = 0;
|
||||||
j1 = 1;
|
j1 = 1;
|
||||||
} /* upper triangle, YX order: (0,0)->(0,1)->(1,1) */
|
} /* upper triangle, YX order: (0,0)->(0,1)->(1,1) */
|
||||||
|
@ -192,24 +176,24 @@ double noiseSimplexGet2DValue(double x, double y)
|
||||||
int gi1 = _permutationsMod12[ii + i1 + _permutations2[jj + j1]];
|
int gi1 = _permutationsMod12[ii + i1 + _permutations2[jj + j1]];
|
||||||
int gi2 = _permutationsMod12[ii + 1 + _permutations2[jj + 1]];
|
int gi2 = _permutationsMod12[ii + 1 + _permutations2[jj + 1]];
|
||||||
/* Calculate the contribution from the three corners */
|
/* Calculate the contribution from the three corners */
|
||||||
double t0 = 0.5 - x0 * x0 - y0*y0;
|
double t0 = 0.5 - x0 * x0 - y0 * y0;
|
||||||
if (t0 < 0) n0 = 0.0;
|
if (t0 < 0)
|
||||||
else
|
n0 = 0.0;
|
||||||
{
|
else {
|
||||||
t0 *= t0;
|
t0 *= t0;
|
||||||
n0 = t0 * t0 * _dot2(_grad3[gi0], x0, y0); /* (x,y) of _grad3 used for 2D gradient */
|
n0 = t0 * t0 * _dot2(_grad3[gi0], x0, y0); /* (x,y) of _grad3 used for 2D gradient */
|
||||||
}
|
}
|
||||||
double t1 = 0.5 - x1 * x1 - y1*y1;
|
double t1 = 0.5 - x1 * x1 - y1 * y1;
|
||||||
if (t1 < 0) n1 = 0.0;
|
if (t1 < 0)
|
||||||
else
|
n1 = 0.0;
|
||||||
{
|
else {
|
||||||
t1 *= t1;
|
t1 *= t1;
|
||||||
n1 = t1 * t1 * _dot2(_grad3[gi1], x1, y1);
|
n1 = t1 * t1 * _dot2(_grad3[gi1], x1, y1);
|
||||||
}
|
}
|
||||||
double t2 = 0.5 - x2 * x2 - y2*y2;
|
double t2 = 0.5 - x2 * x2 - y2 * y2;
|
||||||
if (t2 < 0) n2 = 0.0;
|
if (t2 < 0)
|
||||||
else
|
n2 = 0.0;
|
||||||
{
|
else {
|
||||||
t2 *= t2;
|
t2 *= t2;
|
||||||
n2 = t2 * t2 * _dot2(_grad3[gi2], x2, y2);
|
n2 = t2 * t2 * _dot2(_grad3[gi2], x2, y2);
|
||||||
}
|
}
|
||||||
|
@ -218,8 +202,7 @@ double noiseSimplexGet2DValue(double x, double y)
|
||||||
return 35.0 * (n0 + n1 + n2) + 0.5;
|
return 35.0 * (n0 + n1 + n2) + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
double noiseSimplexGet3DValue(double x, double y, double z)
|
double noiseSimplexGet3DValue(double x, double y, double z) {
|
||||||
{
|
|
||||||
double n0, n1, n2, n3; /* Noise contributions from the four corners */
|
double n0, n1, n2, n3; /* Noise contributions from the four corners */
|
||||||
/* Skew the input space to determine which simplex cell we're in */
|
/* Skew the input space to determine which simplex cell we're in */
|
||||||
double s = (x + y + z) * _F3; /* Very nice and simple skew factor for 3D */
|
double s = (x + y + z) * _F3; /* Very nice and simple skew factor for 3D */
|
||||||
|
@ -237,10 +220,8 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
Determine which simplex we are in. */
|
Determine which simplex we are in. */
|
||||||
int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */
|
int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */
|
||||||
int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */
|
int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */
|
||||||
if (x0 >= y0)
|
if (x0 >= y0) {
|
||||||
{
|
if (y0 >= z0) {
|
||||||
if (y0 >= z0)
|
|
||||||
{
|
|
||||||
i1 = 1;
|
i1 = 1;
|
||||||
j1 = 0;
|
j1 = 0;
|
||||||
k1 = 0;
|
k1 = 0;
|
||||||
|
@ -248,8 +229,7 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
j2 = 1;
|
j2 = 1;
|
||||||
k2 = 0;
|
k2 = 0;
|
||||||
} /* X Y Z order */
|
} /* X Y Z order */
|
||||||
else if (x0 >= z0)
|
else if (x0 >= z0) {
|
||||||
{
|
|
||||||
i1 = 1;
|
i1 = 1;
|
||||||
j1 = 0;
|
j1 = 0;
|
||||||
k1 = 0;
|
k1 = 0;
|
||||||
|
@ -257,8 +237,7 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
j2 = 0;
|
j2 = 0;
|
||||||
k2 = 1;
|
k2 = 1;
|
||||||
} /* X Z Y order */
|
} /* X Z Y order */
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
i1 = 0;
|
i1 = 0;
|
||||||
j1 = 0;
|
j1 = 0;
|
||||||
k1 = 1;
|
k1 = 1;
|
||||||
|
@ -266,11 +245,8 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
j2 = 0;
|
j2 = 0;
|
||||||
k2 = 1;
|
k2 = 1;
|
||||||
} /* Z X Y order */
|
} /* Z X Y order */
|
||||||
}
|
} else { /* x0<y0 */
|
||||||
else
|
if (y0 < z0) {
|
||||||
{ /* x0<y0 */
|
|
||||||
if (y0 < z0)
|
|
||||||
{
|
|
||||||
i1 = 0;
|
i1 = 0;
|
||||||
j1 = 0;
|
j1 = 0;
|
||||||
k1 = 1;
|
k1 = 1;
|
||||||
|
@ -278,8 +254,7 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
j2 = 1;
|
j2 = 1;
|
||||||
k2 = 1;
|
k2 = 1;
|
||||||
} /* Z Y X order */
|
} /* Z Y X order */
|
||||||
else if (x0 < z0)
|
else if (x0 < z0) {
|
||||||
{
|
|
||||||
i1 = 0;
|
i1 = 0;
|
||||||
j1 = 1;
|
j1 = 1;
|
||||||
k1 = 0;
|
k1 = 0;
|
||||||
|
@ -287,8 +262,7 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
j2 = 1;
|
j2 = 1;
|
||||||
k2 = 1;
|
k2 = 1;
|
||||||
} /* Y Z X order */
|
} /* Y Z X order */
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
i1 = 0;
|
i1 = 0;
|
||||||
j1 = 1;
|
j1 = 1;
|
||||||
k1 = 0;
|
k1 = 0;
|
||||||
|
@ -319,31 +293,31 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
int gi2 = _permutationsMod12[ii + i2 + _permutations2[jj + j2 + _permutations2[kk + k2]]];
|
int gi2 = _permutationsMod12[ii + i2 + _permutations2[jj + j2 + _permutations2[kk + k2]]];
|
||||||
int gi3 = _permutationsMod12[ii + 1 + _permutations2[jj + 1 + _permutations2[kk + 1]]];
|
int gi3 = _permutationsMod12[ii + 1 + _permutations2[jj + 1 + _permutations2[kk + 1]]];
|
||||||
/* Calculate the contribution from the four corners */
|
/* Calculate the contribution from the four corners */
|
||||||
double t0 = 0.6 - x0 * x0 - y0 * y0 - z0*z0;
|
double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
|
||||||
if (t0 < 0) n0 = 0.0;
|
if (t0 < 0)
|
||||||
else
|
n0 = 0.0;
|
||||||
{
|
else {
|
||||||
t0 *= t0;
|
t0 *= t0;
|
||||||
n0 = t0 * t0 * _dot3(_grad3[gi0], x0, y0, z0);
|
n0 = t0 * t0 * _dot3(_grad3[gi0], x0, y0, z0);
|
||||||
}
|
}
|
||||||
double t1 = 0.6 - x1 * x1 - y1 * y1 - z1*z1;
|
double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
|
||||||
if (t1 < 0) n1 = 0.0;
|
if (t1 < 0)
|
||||||
else
|
n1 = 0.0;
|
||||||
{
|
else {
|
||||||
t1 *= t1;
|
t1 *= t1;
|
||||||
n1 = t1 * t1 * _dot3(_grad3[gi1], x1, y1, z1);
|
n1 = t1 * t1 * _dot3(_grad3[gi1], x1, y1, z1);
|
||||||
}
|
}
|
||||||
double t2 = 0.6 - x2 * x2 - y2 * y2 - z2*z2;
|
double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
|
||||||
if (t2 < 0) n2 = 0.0;
|
if (t2 < 0)
|
||||||
else
|
n2 = 0.0;
|
||||||
{
|
else {
|
||||||
t2 *= t2;
|
t2 *= t2;
|
||||||
n2 = t2 * t2 * _dot3(_grad3[gi2], x2, y2, z2);
|
n2 = t2 * t2 * _dot3(_grad3[gi2], x2, y2, z2);
|
||||||
}
|
}
|
||||||
double t3 = 0.6 - x3 * x3 - y3 * y3 - z3*z3;
|
double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
|
||||||
if (t3 < 0) n3 = 0.0;
|
if (t3 < 0)
|
||||||
else
|
n3 = 0.0;
|
||||||
{
|
else {
|
||||||
t3 *= t3;
|
t3 *= t3;
|
||||||
n3 = t3 * t3 * _dot3(_grad3[gi3], x3, y3, z3);
|
n3 = t3 * t3 * _dot3(_grad3[gi3], x3, y3, z3);
|
||||||
}
|
}
|
||||||
|
@ -352,8 +326,7 @@ double noiseSimplexGet3DValue(double x, double y, double z)
|
||||||
return 16.0 * (n0 + n1 + n2 + n3) + 0.5;
|
return 16.0 * (n0 + n1 + n2 + n3) + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
double noiseSimplexGet4DValue(double x, double y, double z, double w)
|
double noiseSimplexGet4DValue(double x, double y, double z, double w) {
|
||||||
{
|
|
||||||
double n0, n1, n2, n3, n4; /* Noise contributions from the five corners */
|
double n0, n1, n2, n3, n4; /* Noise contributions from the five corners */
|
||||||
/* Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in */
|
/* Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in */
|
||||||
double s = (x + y + z + w) * _F4; /* Factor for 4D skewing */
|
double s = (x + y + z + w) * _F4; /* Factor for 4D skewing */
|
||||||
|
@ -379,18 +352,30 @@ double noiseSimplexGet4DValue(double x, double y, double z, double w)
|
||||||
int ranky = 0;
|
int ranky = 0;
|
||||||
int rankz = 0;
|
int rankz = 0;
|
||||||
int rankw = 0;
|
int rankw = 0;
|
||||||
if (x0 > y0) rankx++;
|
if (x0 > y0)
|
||||||
else ranky++;
|
rankx++;
|
||||||
if (x0 > z0) rankx++;
|
else
|
||||||
else rankz++;
|
ranky++;
|
||||||
if (x0 > w0) rankx++;
|
if (x0 > z0)
|
||||||
else rankw++;
|
rankx++;
|
||||||
if (y0 > z0) ranky++;
|
else
|
||||||
else rankz++;
|
rankz++;
|
||||||
if (y0 > w0) ranky++;
|
if (x0 > w0)
|
||||||
else rankw++;
|
rankx++;
|
||||||
if (z0 > w0) rankz++;
|
else
|
||||||
else rankw++;
|
rankw++;
|
||||||
|
if (y0 > z0)
|
||||||
|
ranky++;
|
||||||
|
else
|
||||||
|
rankz++;
|
||||||
|
if (y0 > w0)
|
||||||
|
ranky++;
|
||||||
|
else
|
||||||
|
rankw++;
|
||||||
|
if (z0 > w0)
|
||||||
|
rankz++;
|
||||||
|
else
|
||||||
|
rankw++;
|
||||||
int i1, j1, k1, l1; /* The integer offsets for the second simplex corner */
|
int i1, j1, k1, l1; /* The integer offsets for the second simplex corner */
|
||||||
int i2, j2, k2, l2; /* The integer offsets for the third simplex corner */
|
int i2, j2, k2, l2; /* The integer offsets for the third simplex corner */
|
||||||
int i3, j3, k3, l3; /* The integer offsets for the fourth simplex corner */
|
int i3, j3, k3, l3; /* The integer offsets for the fourth simplex corner */
|
||||||
|
@ -436,43 +421,46 @@ double noiseSimplexGet4DValue(double x, double y, double z, double w)
|
||||||
int kk = k & 255;
|
int kk = k & 255;
|
||||||
int ll = l & 255;
|
int ll = l & 255;
|
||||||
int gi0 = _permutations2[ii + _permutations2[jj + _permutations2[kk + _permutations2[ll]]]] % 32;
|
int gi0 = _permutations2[ii + _permutations2[jj + _permutations2[kk + _permutations2[ll]]]] % 32;
|
||||||
int gi1 = _permutations2[ii + i1 + _permutations2[jj + j1 + _permutations2[kk + k1 + _permutations2[ll + l1]]]] % 32;
|
int gi1 =
|
||||||
int gi2 = _permutations2[ii + i2 + _permutations2[jj + j2 + _permutations2[kk + k2 + _permutations2[ll + l2]]]] % 32;
|
_permutations2[ii + i1 + _permutations2[jj + j1 + _permutations2[kk + k1 + _permutations2[ll + l1]]]] % 32;
|
||||||
int gi3 = _permutations2[ii + i3 + _permutations2[jj + j3 + _permutations2[kk + k3 + _permutations2[ll + l3]]]] % 32;
|
int gi2 =
|
||||||
|
_permutations2[ii + i2 + _permutations2[jj + j2 + _permutations2[kk + k2 + _permutations2[ll + l2]]]] % 32;
|
||||||
|
int gi3 =
|
||||||
|
_permutations2[ii + i3 + _permutations2[jj + j3 + _permutations2[kk + k3 + _permutations2[ll + l3]]]] % 32;
|
||||||
int gi4 = _permutations2[ii + 1 + _permutations2[jj + 1 + _permutations2[kk + 1 + _permutations2[ll + 1]]]] % 32;
|
int gi4 = _permutations2[ii + 1 + _permutations2[jj + 1 + _permutations2[kk + 1 + _permutations2[ll + 1]]]] % 32;
|
||||||
/* Calculate the contribution from the five corners */
|
/* Calculate the contribution from the five corners */
|
||||||
double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0*w0;
|
double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
|
||||||
if (t0 < 0) n0 = 0.0;
|
if (t0 < 0)
|
||||||
else
|
n0 = 0.0;
|
||||||
{
|
else {
|
||||||
t0 *= t0;
|
t0 *= t0;
|
||||||
n0 = t0 * t0 * _dot4(_grad4[gi0], x0, y0, z0, w0);
|
n0 = t0 * t0 * _dot4(_grad4[gi0], x0, y0, z0, w0);
|
||||||
}
|
}
|
||||||
double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1*w1;
|
double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
|
||||||
if (t1 < 0) n1 = 0.0;
|
if (t1 < 0)
|
||||||
else
|
n1 = 0.0;
|
||||||
{
|
else {
|
||||||
t1 *= t1;
|
t1 *= t1;
|
||||||
n1 = t1 * t1 * _dot4(_grad4[gi1], x1, y1, z1, w1);
|
n1 = t1 * t1 * _dot4(_grad4[gi1], x1, y1, z1, w1);
|
||||||
}
|
}
|
||||||
double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2*w2;
|
double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
|
||||||
if (t2 < 0) n2 = 0.0;
|
if (t2 < 0)
|
||||||
else
|
n2 = 0.0;
|
||||||
{
|
else {
|
||||||
t2 *= t2;
|
t2 *= t2;
|
||||||
n2 = t2 * t2 * _dot4(_grad4[gi2], x2, y2, z2, w2);
|
n2 = t2 * t2 * _dot4(_grad4[gi2], x2, y2, z2, w2);
|
||||||
}
|
}
|
||||||
double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3*w3;
|
double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
|
||||||
if (t3 < 0) n3 = 0.0;
|
if (t3 < 0)
|
||||||
else
|
n3 = 0.0;
|
||||||
{
|
else {
|
||||||
t3 *= t3;
|
t3 *= t3;
|
||||||
n3 = t3 * t3 * _dot4(_grad4[gi3], x3, y3, z3, w3);
|
n3 = t3 * t3 * _dot4(_grad4[gi3], x3, y3, z3, w3);
|
||||||
}
|
}
|
||||||
double t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4*w4;
|
double t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
|
||||||
if (t4 < 0) n4 = 0.0;
|
if (t4 < 0)
|
||||||
else
|
n4 = 0.0;
|
||||||
{
|
else {
|
||||||
t4 *= t4;
|
t4 *= t4;
|
||||||
n4 = t4 * t4 * _dot4(_grad4[gi4], x4, y4, z4, w4);
|
n4 = t4 * t4 * _dot4(_grad4[gi4], x4, y4, z4, w4);
|
||||||
}
|
}
|
||||||
|
@ -480,31 +468,25 @@ double noiseSimplexGet4DValue(double x, double y, double z, double w)
|
||||||
return 13.5 * (n0 + n1 + n2 + n3 + n4) + 0.5;
|
return 13.5 * (n0 + n1 + n2 + n3 + n4) + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseFunctionSimplex::getBase2d(double x, double y) const
|
double NoiseFunctionSimplex::getBase2d(double x, double y) const {
|
||||||
{
|
|
||||||
return noiseSimplexGet2DValue(x, y);
|
return noiseSimplexGet2DValue(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseFunctionSimplex::getBase3d(double x, double y, double z) const
|
double NoiseFunctionSimplex::getBase3d(double x, double y, double z) const {
|
||||||
{
|
|
||||||
return noiseSimplexGet3DValue(x, y, z);
|
return noiseSimplexGet3DValue(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Texture2D *_valueTexture = NULL;
|
static Texture2D *_valueTexture = NULL;
|
||||||
|
|
||||||
const Texture2D *NoiseFunctionSimplex::getValueTexture()
|
const Texture2D *NoiseFunctionSimplex::getValueTexture() {
|
||||||
{
|
if (!_valueTexture) {
|
||||||
if (!_valueTexture)
|
|
||||||
{
|
|
||||||
const int width = 1024;
|
const int width = 1024;
|
||||||
const int height = 1024;
|
const int height = 1024;
|
||||||
|
|
||||||
_valueTexture = new Texture2D(width, height);
|
_valueTexture = new Texture2D(width, height);
|
||||||
|
|
||||||
for (int x = 0; x < width; x++)
|
for (int x = 0; x < width; x++) {
|
||||||
{
|
for (int z = 0; z < height; z++) {
|
||||||
for (int z = 0; z < height; z++)
|
|
||||||
{
|
|
||||||
double val = noiseSimplexGet2DValue((double)x, (double)z);
|
double val = noiseSimplexGet2DValue((double)x, (double)z);
|
||||||
_valueTexture->setPixel(x, z, Color(val, val, val));
|
_valueTexture->setPixel(x, z, Color(val, val, val));
|
||||||
}
|
}
|
||||||
|
@ -516,27 +498,21 @@ const Texture2D *NoiseFunctionSimplex::getValueTexture()
|
||||||
|
|
||||||
static Texture2D *_normalTexture = NULL;
|
static Texture2D *_normalTexture = NULL;
|
||||||
|
|
||||||
const Texture2D *NoiseFunctionSimplex::getNormalTexture()
|
const Texture2D *NoiseFunctionSimplex::getNormalTexture() {
|
||||||
{
|
if (!_normalTexture) {
|
||||||
if (!_normalTexture)
|
|
||||||
{
|
|
||||||
const int width = 1024;
|
const int width = 1024;
|
||||||
const int height = 1024;
|
const int height = 1024;
|
||||||
|
|
||||||
_normalTexture = new Texture2D(width, height);
|
_normalTexture = new Texture2D(width, height);
|
||||||
|
|
||||||
for (int x = 0; x < width; x++)
|
for (int x = 0; x < width; x++) {
|
||||||
{
|
for (int z = 0; z < height; z++) {
|
||||||
for (int z = 0; z < height; z++)
|
|
||||||
{
|
|
||||||
double vcenter = noiseSimplexGet2DValue(0.01 * (double)x, 0.01 * (double)z);
|
double vcenter = noiseSimplexGet2DValue(0.01 * (double)x, 0.01 * (double)z);
|
||||||
double vsouth = noiseSimplexGet2DValue(0.01 * (double)x, 0.01 * (double)z + 0.001);
|
double vsouth = noiseSimplexGet2DValue(0.01 * (double)x, 0.01 * (double)z + 0.001);
|
||||||
double veast = noiseSimplexGet2DValue(0.01 * (double)x + 0.001, 0.01 * (double)z);
|
double veast = noiseSimplexGet2DValue(0.01 * (double)x + 0.001, 0.01 * (double)z);
|
||||||
|
|
||||||
Vector3 normal = Geometry::getNormalFromTriangle(Vector3(0.0, vcenter, 0.0),
|
Vector3 normal = Geometry::getNormalFromTriangle(Vector3(0.0, vcenter, 0.0), Vector3(0.0, vsouth, 0.01),
|
||||||
Vector3(0.0, vsouth, 0.01),
|
Vector3(0.01, veast, 0.0));
|
||||||
Vector3(0.01, veast, 0.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
_normalTexture->setPixel(x, z, Color(normal.x, normal.y, normal.z));
|
_normalTexture->setPixel(x, z, Color(normal.x, normal.y, normal.z));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,14 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class NoiseFunctionSimplex:public FractalNoise
|
class NoiseFunctionSimplex : public FractalNoise {
|
||||||
{
|
|
||||||
virtual double getBase2d(double x, double y) const override;
|
virtual double getBase2d(double x, double y) const override;
|
||||||
virtual double getBase3d(double x, double y, double z) const override;
|
virtual double getBase3d(double x, double y, double z) const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const Texture2D *getValueTexture();
|
static const Texture2D *getValueTexture();
|
||||||
static const Texture2D *getNormalTexture();
|
static const Texture2D *getNormalTexture();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
|
|
||||||
/* NoiseGenerator class */
|
/* NoiseGenerator class */
|
||||||
|
|
||||||
NoiseGenerator::NoiseGenerator()
|
NoiseGenerator::NoiseGenerator() {
|
||||||
{
|
|
||||||
function.algorithm = NOISE_FUNCTION_SIMPLEX;
|
function.algorithm = NOISE_FUNCTION_SIMPLEX;
|
||||||
function.ridge_factor = 0.0;
|
function.ridge_factor = 0.0;
|
||||||
function.curve_factor = 0.0;
|
function.curve_factor = 0.0;
|
||||||
|
@ -25,12 +24,10 @@ NoiseGenerator::NoiseGenerator()
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
NoiseGenerator::~NoiseGenerator()
|
NoiseGenerator::~NoiseGenerator() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::save(PackStream* stream) const
|
void NoiseGenerator::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
x = (int)function.algorithm;
|
x = (int)function.algorithm;
|
||||||
|
@ -41,9 +38,8 @@ void NoiseGenerator::save(PackStream* stream) const
|
||||||
stream->write(&height_offset);
|
stream->write(&height_offset);
|
||||||
stream->write(&level_count);
|
stream->write(&level_count);
|
||||||
|
|
||||||
for (x = 0; x < level_count; x++)
|
for (x = 0; x < level_count; x++) {
|
||||||
{
|
const NoiseLevel *level = levels + x;
|
||||||
const NoiseLevel* level = levels + x;
|
|
||||||
|
|
||||||
stream->write(&level->frequency);
|
stream->write(&level->frequency);
|
||||||
stream->write(&level->amplitude);
|
stream->write(&level->amplitude);
|
||||||
|
@ -53,8 +49,7 @@ void NoiseGenerator::save(PackStream* stream) const
|
||||||
state.save(stream);
|
state.save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::load(PackStream* stream)
|
void NoiseGenerator::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
stream->read(&x);
|
stream->read(&x);
|
||||||
|
@ -65,14 +60,12 @@ void NoiseGenerator::load(PackStream* stream)
|
||||||
stream->read(&height_offset);
|
stream->read(&height_offset);
|
||||||
stream->read(&level_count);
|
stream->read(&level_count);
|
||||||
|
|
||||||
if (level_count > MAX_LEVEL_COUNT)
|
if (level_count > MAX_LEVEL_COUNT) {
|
||||||
{
|
|
||||||
level_count = MAX_LEVEL_COUNT;
|
level_count = MAX_LEVEL_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x = 0; x < level_count; x++)
|
for (x = 0; x < level_count; x++) {
|
||||||
{
|
NoiseLevel *level = levels + x;
|
||||||
NoiseLevel* level = levels + x;
|
|
||||||
|
|
||||||
stream->read(&level->frequency);
|
stream->read(&level->frequency);
|
||||||
stream->read(&level->amplitude);
|
stream->read(&level->amplitude);
|
||||||
|
@ -84,8 +77,7 @@ void NoiseGenerator::load(PackStream* stream)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::copy(NoiseGenerator* destination) const
|
void NoiseGenerator::copy(NoiseGenerator *destination) const {
|
||||||
{
|
|
||||||
destination->function = function;
|
destination->function = function;
|
||||||
destination->height_offset = height_offset;
|
destination->height_offset = height_offset;
|
||||||
destination->level_count = level_count;
|
destination->level_count = level_count;
|
||||||
|
@ -97,16 +89,13 @@ void NoiseGenerator::copy(NoiseGenerator* destination) const
|
||||||
destination->validate();
|
destination->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::validate()
|
void NoiseGenerator::validate() {
|
||||||
{
|
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
if (function.algorithm < 0 || function.algorithm > NOISE_FUNCTION_SIMPLEX)
|
if (function.algorithm < 0 || function.algorithm > NOISE_FUNCTION_SIMPLEX) {
|
||||||
{
|
|
||||||
function.algorithm = NOISE_FUNCTION_SIMPLEX;
|
function.algorithm = NOISE_FUNCTION_SIMPLEX;
|
||||||
}
|
}
|
||||||
switch (function.algorithm)
|
switch (function.algorithm) {
|
||||||
{
|
|
||||||
case NOISE_FUNCTION_PERLIN:
|
case NOISE_FUNCTION_PERLIN:
|
||||||
_func_noise_1d = noisePerlinGet1DValue;
|
_func_noise_1d = noisePerlinGet1DValue;
|
||||||
_func_noise_2d = noisePerlinGet2DValue;
|
_func_noise_2d = noisePerlinGet2DValue;
|
||||||
|
@ -121,103 +110,86 @@ void NoiseGenerator::validate()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function.ridge_factor > 0.5)
|
if (function.ridge_factor > 0.5) {
|
||||||
{
|
|
||||||
function.ridge_factor = 0.5;
|
function.ridge_factor = 0.5;
|
||||||
}
|
}
|
||||||
if (function.ridge_factor < -0.5)
|
if (function.ridge_factor < -0.5) {
|
||||||
{
|
|
||||||
function.ridge_factor = -0.5;
|
function.ridge_factor = -0.5;
|
||||||
}
|
}
|
||||||
if (function.curve_factor > 1.0)
|
if (function.curve_factor > 1.0) {
|
||||||
{
|
|
||||||
function.curve_factor = 1.0;
|
function.curve_factor = 1.0;
|
||||||
}
|
}
|
||||||
if (function.curve_factor < -1.0)
|
if (function.curve_factor < -1.0) {
|
||||||
{
|
|
||||||
function.curve_factor = -1.0;
|
function.curve_factor = -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_min_value = height_offset;
|
_min_value = height_offset;
|
||||||
_max_value = height_offset;
|
_max_value = height_offset;
|
||||||
for (x = 0; x < level_count; x++)
|
for (x = 0; x < level_count; x++) {
|
||||||
{
|
|
||||||
_min_value += levels[x].minvalue;
|
_min_value += levels[x].minvalue;
|
||||||
_max_value += levels[x].minvalue + levels[x].amplitude;
|
_max_value += levels[x].minvalue + levels[x].amplitude;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::setState(const NoiseState &state)
|
void NoiseGenerator::setState(const NoiseState &state) {
|
||||||
{
|
|
||||||
state.copy(&this->state);
|
state.copy(&this->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::randomizeOffsets()
|
void NoiseGenerator::randomizeOffsets() {
|
||||||
{
|
|
||||||
state.randomizeOffsets();
|
state.randomizeOffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
NoiseGenerator::NoiseFunction NoiseGenerator::getFunction()
|
NoiseGenerator::NoiseFunction NoiseGenerator::getFunction() {
|
||||||
{
|
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::setFunction(NoiseFunction* function)
|
void NoiseGenerator::setFunction(NoiseFunction *function) {
|
||||||
{
|
|
||||||
this->function = *function;
|
this->function = *function;
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y), double (*func3d)(double x, double y, double z))
|
void NoiseGenerator::setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y),
|
||||||
{
|
double (*func3d)(double x, double y, double z)) {
|
||||||
_func_noise_1d = func1d;
|
_func_noise_1d = func1d;
|
||||||
_func_noise_2d = func2d;
|
_func_noise_2d = func2d;
|
||||||
_func_noise_3d = func3d;
|
_func_noise_3d = func3d;
|
||||||
function.algorithm = NOISE_FUNCTION_CUSTOM;
|
function.algorithm = NOISE_FUNCTION_CUSTOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::setFunctionParams(NoiseFunctionAlgorithm algorithm, double ridge_factor, double curve_factor)
|
void NoiseGenerator::setFunctionParams(NoiseFunctionAlgorithm algorithm, double ridge_factor, double curve_factor) {
|
||||||
{
|
|
||||||
NoiseFunction function = {algorithm, ridge_factor, curve_factor};
|
NoiseFunction function = {algorithm, ridge_factor, curve_factor};
|
||||||
setFunction(&function);
|
setFunction(&function);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::forceValue(double value)
|
void NoiseGenerator::forceValue(double value) {
|
||||||
{
|
|
||||||
clearLevels();
|
clearLevels();
|
||||||
height_offset = value;
|
height_offset = value;
|
||||||
addLevelSimple(1.0, 0.0, 0.0); /* FIXME Should not be needed */
|
addLevelSimple(1.0, 0.0, 0.0); /* FIXME Should not be needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::getRange(double* minvalue, double* maxvalue) const
|
void NoiseGenerator::getRange(double *minvalue, double *maxvalue) const {
|
||||||
{
|
|
||||||
*minvalue = _min_value;
|
*minvalue = _min_value;
|
||||||
*maxvalue = _max_value;
|
*maxvalue = _max_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NoiseGenerator::getLevelCount() const
|
int NoiseGenerator::getLevelCount() const {
|
||||||
{
|
|
||||||
return level_count;
|
return level_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::clearLevels()
|
void NoiseGenerator::clearLevels() {
|
||||||
{
|
|
||||||
level_count = 0;
|
level_count = 0;
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::addLevel(NoiseLevel level)
|
void NoiseGenerator::addLevel(NoiseLevel level) {
|
||||||
{
|
if (level_count < MAX_LEVEL_COUNT) {
|
||||||
if (level_count < MAX_LEVEL_COUNT)
|
|
||||||
{
|
|
||||||
levels[level_count] = level;
|
levels[level_count] = level;
|
||||||
level_count++;
|
level_count++;
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::addLevelSimple(double scaling, double minvalue, double maxvalue)
|
void NoiseGenerator::addLevelSimple(double scaling, double minvalue, double maxvalue) {
|
||||||
{
|
|
||||||
NoiseLevel level;
|
NoiseLevel level;
|
||||||
|
|
||||||
level.frequency = 1.0 / scaling;
|
level.frequency = 1.0 / scaling;
|
||||||
|
@ -227,12 +199,11 @@ void NoiseGenerator::addLevelSimple(double scaling, double minvalue, double maxv
|
||||||
addLevel(level);
|
addLevel(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::addLevels(int level_count, NoiseLevel start_level, double scaling_factor, double amplitude_factor, double center_factor)
|
void NoiseGenerator::addLevels(int level_count, NoiseLevel start_level, double scaling_factor, double amplitude_factor,
|
||||||
{
|
double center_factor) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < level_count; i++)
|
for (i = 0; i < level_count; i++) {
|
||||||
{
|
|
||||||
addLevel(start_level);
|
addLevel(start_level);
|
||||||
start_level.minvalue += start_level.amplitude * (1.0 - amplitude_factor) * center_factor;
|
start_level.minvalue += start_level.amplitude * (1.0 - amplitude_factor) * center_factor;
|
||||||
start_level.frequency /= scaling_factor;
|
start_level.frequency /= scaling_factor;
|
||||||
|
@ -240,8 +211,8 @@ void NoiseGenerator::addLevels(int level_count, NoiseLevel start_level, double s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::addLevelsSimple(int level_count, double scaling, double minvalue, double maxvalue, double center_factor)
|
void NoiseGenerator::addLevelsSimple(int level_count, double scaling, double minvalue, double maxvalue,
|
||||||
{
|
double center_factor) {
|
||||||
NoiseLevel level;
|
NoiseLevel level;
|
||||||
|
|
||||||
level.frequency = 1.0 / scaling;
|
level.frequency = 1.0 / scaling;
|
||||||
|
@ -250,12 +221,9 @@ void NoiseGenerator::addLevelsSimple(int level_count, double scaling, double min
|
||||||
addLevels(level_count, level, 0.5, 0.5, center_factor);
|
addLevels(level_count, level, 0.5, 0.5, center_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::removeLevel(int level)
|
void NoiseGenerator::removeLevel(int level) {
|
||||||
{
|
if (level >= 0 && level < level_count) {
|
||||||
if (level >= 0 && level < level_count)
|
if (level_count > 1 && level < level_count - 1) {
|
||||||
{
|
|
||||||
if (level_count > 1 && level < level_count - 1)
|
|
||||||
{
|
|
||||||
memmove(levels + level, levels + level + 1, sizeof(NoiseLevel) * (level_count - level - 1));
|
memmove(levels + level, levels + level + 1, sizeof(NoiseLevel) * (level_count - level - 1));
|
||||||
}
|
}
|
||||||
level_count--;
|
level_count--;
|
||||||
|
@ -263,30 +231,23 @@ void NoiseGenerator::removeLevel(int level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int NoiseGenerator::getLevel(int level, NoiseLevel* params) const
|
int NoiseGenerator::getLevel(int level, NoiseLevel *params) const {
|
||||||
{
|
if (level >= 0 && level < level_count) {
|
||||||
if (level >= 0 && level < level_count)
|
|
||||||
{
|
|
||||||
*params = levels[level];
|
*params = levels[level];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::setLevel(int index, NoiseLevel level)
|
void NoiseGenerator::setLevel(int index, NoiseLevel level) {
|
||||||
{
|
if (index >= 0 && index < level_count) {
|
||||||
if (index >= 0 && index < level_count)
|
|
||||||
{
|
|
||||||
levels[index] = level;
|
levels[index] = level;
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::setLevelSimple(int index, double scaling, double minvalue, double maxvalue)
|
void NoiseGenerator::setLevelSimple(int index, double scaling, double minvalue, double maxvalue) {
|
||||||
{
|
|
||||||
NoiseLevel level;
|
NoiseLevel level;
|
||||||
|
|
||||||
level.frequency = 1.0 / scaling;
|
level.frequency = 1.0 / scaling;
|
||||||
|
@ -296,14 +257,12 @@ void NoiseGenerator::setLevelSimple(int index, double scaling, double minvalue,
|
||||||
setLevel(index, level);
|
setLevel(index, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseGenerator::normalizeAmplitude(double minvalue, double maxvalue, int adjust_scaling)
|
void NoiseGenerator::normalizeAmplitude(double minvalue, double maxvalue, int adjust_scaling) {
|
||||||
{
|
|
||||||
int level;
|
int level;
|
||||||
double current_minvalue, current_maxvalue, current_amplitude;
|
double current_minvalue, current_maxvalue, current_amplitude;
|
||||||
double target_amplitude, factor;
|
double target_amplitude, factor;
|
||||||
|
|
||||||
if (level_count == 0)
|
if (level_count == 0) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,12 +271,10 @@ void NoiseGenerator::normalizeAmplitude(double minvalue, double maxvalue, int ad
|
||||||
current_amplitude = current_maxvalue - current_minvalue;
|
current_amplitude = current_maxvalue - current_minvalue;
|
||||||
factor = target_amplitude / current_amplitude;
|
factor = target_amplitude / current_amplitude;
|
||||||
|
|
||||||
for (level = 0; level < level_count; level++)
|
for (level = 0; level < level_count; level++) {
|
||||||
{
|
|
||||||
levels[level].minvalue *= factor;
|
levels[level].minvalue *= factor;
|
||||||
levels[level].amplitude *= factor;
|
levels[level].amplitude *= factor;
|
||||||
if (adjust_scaling)
|
if (adjust_scaling) {
|
||||||
{
|
|
||||||
levels[level].frequency /= factor;
|
levels[level].frequency /= factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,36 +282,24 @@ void NoiseGenerator::normalizeAmplitude(double minvalue, double maxvalue, int ad
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double _fixValue(double value, double ridge, double curve)
|
static inline double _fixValue(double value, double ridge, double curve) {
|
||||||
{
|
if (value < 0.0) {
|
||||||
if (value < 0.0)
|
|
||||||
{
|
|
||||||
value = 0.0;
|
value = 0.0;
|
||||||
}
|
} else if (value > 1.0) {
|
||||||
else if (value > 1.0)
|
|
||||||
{
|
|
||||||
value = 1.0;
|
value = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curve > 0.0)
|
if (curve > 0.0) {
|
||||||
{
|
|
||||||
value = value * (1.0 - curve) + sqrt(value) * curve;
|
value = value * (1.0 - curve) + sqrt(value) * curve;
|
||||||
}
|
} else if (curve < 0.0) {
|
||||||
else if (curve < 0.0)
|
|
||||||
{
|
|
||||||
value = value * (1.0 - curve) + value * value * curve;
|
value = value * (1.0 - curve) + value * value * curve;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ridge > 0.0)
|
if (ridge > 0.0) {
|
||||||
{
|
|
||||||
return fabs(value - ridge) / (1.0 - ridge);
|
return fabs(value - ridge) / (1.0 - ridge);
|
||||||
}
|
} else if (ridge < 0.0) {
|
||||||
else if (ridge < 0.0)
|
|
||||||
{
|
|
||||||
return 1.0 - fabs(value - 1.0 - ridge) / (1.0 + ridge);
|
return 1.0 - fabs(value - 1.0 - ridge) / (1.0 + ridge);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
/*if (ridge > 0.0)
|
/*if (ridge > 0.0)
|
||||||
|
@ -371,55 +316,43 @@ static inline double _fixValue(double value, double ridge, double curve)
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double NoiseGenerator::_get1DLevelValue(const NoiseLevel *level, const NoiseState::NoiseOffset &offset,
|
||||||
|
double x) const {
|
||||||
|
return level->minvalue +
|
||||||
inline double NoiseGenerator::_get1DLevelValue(const NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x) const
|
_fixValue(_func_noise_1d(x * level->frequency + offset.x), function.ridge_factor, function.curve_factor) *
|
||||||
{
|
level->amplitude;
|
||||||
return level->minvalue + _fixValue(_func_noise_1d(x * level->frequency + offset.x), function.ridge_factor, function.curve_factor) * level->amplitude;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get1DLevel(int level, double x) const
|
double NoiseGenerator::get1DLevel(int level, double x) const {
|
||||||
{
|
if (level >= 0 && level < level_count) {
|
||||||
if (level >= 0 && level < level_count)
|
|
||||||
{
|
|
||||||
return _get1DLevelValue(levels + level, state.level_offsets[level], x);
|
return _get1DLevelValue(levels + level, state.level_offsets[level], x);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get1DTotal(double x) const
|
double NoiseGenerator::get1DTotal(double x) const {
|
||||||
{
|
|
||||||
int level;
|
int level;
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
result = 0.0;
|
result = 0.0;
|
||||||
for (level = 0; level < level_count; level++)
|
for (level = 0; level < level_count; level++) {
|
||||||
{
|
|
||||||
result += _get1DLevelValue(levels + level, state.level_offsets[level], x);
|
result += _get1DLevelValue(levels + level, state.level_offsets[level], x);
|
||||||
}
|
}
|
||||||
return result + height_offset;
|
return result + height_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get1DDetail(double x, double detail) const
|
double NoiseGenerator::get1DDetail(double x, double detail) const {
|
||||||
{
|
|
||||||
int level;
|
int level;
|
||||||
double result, height, factor;
|
double result, height, factor;
|
||||||
|
|
||||||
result = 0.0;
|
result = 0.0;
|
||||||
for (level = 0; level < level_count; level++)
|
for (level = 0; level < level_count; level++) {
|
||||||
{
|
|
||||||
height = levels[level].amplitude;
|
height = levels[level].amplitude;
|
||||||
factor = 1.0;
|
factor = 1.0;
|
||||||
if (height < detail * 0.25)
|
if (height < detail * 0.25) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else if (height < detail * 0.5) {
|
||||||
else if (height < detail * 0.5)
|
|
||||||
{
|
|
||||||
factor = (detail * 0.5 - height) / 0.25;
|
factor = (detail * 0.5 - height) / 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,55 +361,44 @@ double NoiseGenerator::get1DDetail(double x, double detail) const
|
||||||
return result + height_offset;
|
return result + height_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double NoiseGenerator::_get2DLevelValue(const NoiseLevel *level, const NoiseState::NoiseOffset &offset, double x,
|
||||||
|
double y) const {
|
||||||
|
return level->minvalue +
|
||||||
inline double NoiseGenerator::_get2DLevelValue(const NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y) const
|
_fixValue(_func_noise_2d(x * level->frequency + offset.x, y * level->frequency + offset.y),
|
||||||
{
|
function.ridge_factor, function.curve_factor) *
|
||||||
return level->minvalue + _fixValue(_func_noise_2d(x * level->frequency + offset.x, y * level->frequency + offset.y), function.ridge_factor, function.curve_factor) * level->amplitude;
|
level->amplitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get2DLevel(int level, double x, double y) const
|
double NoiseGenerator::get2DLevel(int level, double x, double y) const {
|
||||||
{
|
if (level >= 0 && level < level_count) {
|
||||||
if (level >= 0 && level < level_count)
|
|
||||||
{
|
|
||||||
return _get2DLevelValue(levels + level, state.level_offsets[level], x, y);
|
return _get2DLevelValue(levels + level, state.level_offsets[level], x, y);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get2DTotal(double x, double y) const
|
double NoiseGenerator::get2DTotal(double x, double y) const {
|
||||||
{
|
|
||||||
int level;
|
int level;
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
result = 0.0;
|
result = 0.0;
|
||||||
for (level = 0; level < level_count; level++)
|
for (level = 0; level < level_count; level++) {
|
||||||
{
|
|
||||||
result += _get2DLevelValue(levels + level, state.level_offsets[level], x, y);
|
result += _get2DLevelValue(levels + level, state.level_offsets[level], x, y);
|
||||||
}
|
}
|
||||||
return result + height_offset;
|
return result + height_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get2DDetail(double x, double y, double detail) const
|
double NoiseGenerator::get2DDetail(double x, double y, double detail) const {
|
||||||
{
|
|
||||||
int level;
|
int level;
|
||||||
double result, height, factor;
|
double result, height, factor;
|
||||||
|
|
||||||
result = 0.0;
|
result = 0.0;
|
||||||
for (level = 0; level < level_count; level++)
|
for (level = 0; level < level_count; level++) {
|
||||||
{
|
|
||||||
height = levels[level].amplitude;
|
height = levels[level].amplitude;
|
||||||
factor = 1.0;
|
factor = 1.0;
|
||||||
if (height < detail * 0.25)
|
if (height < detail * 0.25) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else if (height < detail * 0.5) {
|
||||||
else if (height < detail * 0.5)
|
|
||||||
{
|
|
||||||
factor = (detail * 0.5 - height) / 0.25;
|
factor = (detail * 0.5 - height) / 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,55 +407,45 @@ double NoiseGenerator::get2DDetail(double x, double y, double detail) const
|
||||||
return result + height_offset;
|
return result + height_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double NoiseGenerator::_get3DLevelValue(const NoiseLevel *level, const NoiseState::NoiseOffset &offset, double x,
|
||||||
|
double y, double z) const {
|
||||||
|
return level->minvalue +
|
||||||
inline double NoiseGenerator::_get3DLevelValue(const NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y, double z) const
|
_fixValue(_func_noise_3d(x * level->frequency + offset.x, y * level->frequency + offset.y,
|
||||||
{
|
z * level->frequency + offset.z),
|
||||||
return level->minvalue + _fixValue(_func_noise_3d(x * level->frequency + offset.x, y * level->frequency + offset.y, z * level->frequency + offset.z), function.ridge_factor, function.curve_factor) * level->amplitude;
|
function.ridge_factor, function.curve_factor) *
|
||||||
|
level->amplitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get3DLevel(int level, double x, double y, double z) const
|
double NoiseGenerator::get3DLevel(int level, double x, double y, double z) const {
|
||||||
{
|
if (level >= 0 && level < level_count) {
|
||||||
if (level >= 0 && level < level_count)
|
|
||||||
{
|
|
||||||
return _get3DLevelValue(levels + level, state.level_offsets[level], x, y, z);
|
return _get3DLevelValue(levels + level, state.level_offsets[level], x, y, z);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get3DTotal(double x, double y, double z) const
|
double NoiseGenerator::get3DTotal(double x, double y, double z) const {
|
||||||
{
|
|
||||||
int level;
|
int level;
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
result = 0.0;
|
result = 0.0;
|
||||||
for (level = 0; level < level_count; level++)
|
for (level = 0; level < level_count; level++) {
|
||||||
{
|
|
||||||
result += _get3DLevelValue(levels + level, state.level_offsets[level], x, y, z);
|
result += _get3DLevelValue(levels + level, state.level_offsets[level], x, y, z);
|
||||||
}
|
}
|
||||||
return result + height_offset;
|
return result + height_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
double NoiseGenerator::get3DDetail(double x, double y, double z, double detail) const
|
double NoiseGenerator::get3DDetail(double x, double y, double z, double detail) const {
|
||||||
{
|
|
||||||
int level;
|
int level;
|
||||||
double result, height, factor;
|
double result, height, factor;
|
||||||
|
|
||||||
result = 0.0;
|
result = 0.0;
|
||||||
for (level = 0; level < level_count; level++)
|
for (level = 0; level < level_count; level++) {
|
||||||
{
|
|
||||||
height = levels[level].amplitude;
|
height = levels[level].amplitude;
|
||||||
factor = 1.0;
|
factor = 1.0;
|
||||||
if (height < detail * 0.25)
|
if (height < detail * 0.25) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else if (height < detail * 0.5) {
|
||||||
else if (height < detail * 0.5)
|
|
||||||
{
|
|
||||||
factor = (detail * 0.5 - height) / 0.25;
|
factor = (detail * 0.5 - height) / 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,57 +9,53 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT NoiseGenerator
|
class BASICSSHARED_EXPORT NoiseGenerator {
|
||||||
{
|
public:
|
||||||
public:
|
typedef enum { NOISE_FUNCTION_PERLIN, NOISE_FUNCTION_SIMPLEX, NOISE_FUNCTION_CUSTOM } NoiseFunctionAlgorithm;
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
NOISE_FUNCTION_PERLIN,
|
|
||||||
NOISE_FUNCTION_SIMPLEX,
|
|
||||||
NOISE_FUNCTION_CUSTOM
|
|
||||||
} NoiseFunctionAlgorithm;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
NoiseFunctionAlgorithm algorithm;
|
NoiseFunctionAlgorithm algorithm;
|
||||||
double ridge_factor; /* -0.5;0.5 */
|
double ridge_factor; /* -0.5;0.5 */
|
||||||
double curve_factor; /* -1.0;1.0 */
|
double curve_factor; /* -1.0;1.0 */
|
||||||
} NoiseFunction;
|
} NoiseFunction;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
double frequency;
|
double frequency;
|
||||||
double amplitude;
|
double amplitude;
|
||||||
double minvalue;
|
double minvalue;
|
||||||
} NoiseLevel;
|
} NoiseLevel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NoiseGenerator();
|
NoiseGenerator();
|
||||||
virtual ~NoiseGenerator();
|
virtual ~NoiseGenerator();
|
||||||
|
|
||||||
virtual void save(PackStream* stream) const;
|
virtual void save(PackStream *stream) const;
|
||||||
virtual void load(PackStream* stream);
|
virtual void load(PackStream *stream);
|
||||||
virtual void copy(NoiseGenerator* destination) const;
|
virtual void copy(NoiseGenerator *destination) const;
|
||||||
virtual void validate();
|
virtual void validate();
|
||||||
|
|
||||||
inline const NoiseState &getState() const {return state;}
|
inline const NoiseState &getState() const {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
void setState(const NoiseState &state);
|
void setState(const NoiseState &state);
|
||||||
|
|
||||||
void randomizeOffsets();
|
void randomizeOffsets();
|
||||||
NoiseFunction getFunction();
|
NoiseFunction getFunction();
|
||||||
void setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y), double (*func3d)(double x, double y, double z));
|
void setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y),
|
||||||
void setFunction(NoiseFunction* function);
|
double (*func3d)(double x, double y, double z));
|
||||||
|
void setFunction(NoiseFunction *function);
|
||||||
void setFunctionParams(NoiseFunctionAlgorithm algorithm, double ridge_factor, double curve_factor);
|
void setFunctionParams(NoiseFunctionAlgorithm algorithm, double ridge_factor, double curve_factor);
|
||||||
void forceValue(double value);
|
void forceValue(double value);
|
||||||
void getRange(double* minvalue, double* maxvalue) const;
|
void getRange(double *minvalue, double *maxvalue) const;
|
||||||
int getLevelCount() const;
|
int getLevelCount() const;
|
||||||
void clearLevels();
|
void clearLevels();
|
||||||
void addLevel(NoiseLevel level);
|
void addLevel(NoiseLevel level);
|
||||||
void addLevelSimple(double scaling, double minvalue, double maxvalue);
|
void addLevelSimple(double scaling, double minvalue, double maxvalue);
|
||||||
void addLevels(int level_count, NoiseLevel start_level, double scaling_factor, double amplitude_factor, double center_factor);
|
void addLevels(int level_count, NoiseLevel start_level, double scaling_factor, double amplitude_factor,
|
||||||
|
double center_factor);
|
||||||
void addLevelsSimple(int level_count, double scaling, double minvalue, double maxvalue, double center_factor);
|
void addLevelsSimple(int level_count, double scaling, double minvalue, double maxvalue, double center_factor);
|
||||||
void removeLevel(int level);
|
void removeLevel(int level);
|
||||||
int getLevel(int level, NoiseLevel* params) const;
|
int getLevel(int level, NoiseLevel *params) const;
|
||||||
void setLevel(int index, NoiseLevel level);
|
void setLevel(int index, NoiseLevel level);
|
||||||
void setLevelSimple(int index, double scaling, double minvalue, double maxvalue);
|
void setLevelSimple(int index, double scaling, double minvalue, double maxvalue);
|
||||||
void normalizeAmplitude(double minvalue, double maxvalue, int adjust_scaling);
|
void normalizeAmplitude(double minvalue, double maxvalue, int adjust_scaling);
|
||||||
|
@ -73,10 +69,11 @@ public:
|
||||||
double get3DTotal(double x, double y, double z) const;
|
double get3DTotal(double x, double y, double z) const;
|
||||||
double get3DDetail(double x, double y, double z, double detail) const;
|
double get3DDetail(double x, double y, double z, double detail) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double _get1DLevelValue(const NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x) const;
|
double _get1DLevelValue(const NoiseLevel *level, const NoiseState::NoiseOffset &offset, double x) const;
|
||||||
double _get2DLevelValue(const NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y) const;
|
double _get2DLevelValue(const NoiseLevel *level, const NoiseState::NoiseOffset &offset, double x, double y) const;
|
||||||
double _get3DLevelValue(const NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y, double z) const;
|
double _get3DLevelValue(const NoiseLevel *level, const NoiseState::NoiseOffset &offset, double x, double y,
|
||||||
|
double z) const;
|
||||||
|
|
||||||
NoiseFunction function;
|
NoiseFunction function;
|
||||||
double height_offset;
|
double height_offset;
|
||||||
|
@ -91,7 +88,6 @@ private:
|
||||||
double (*_func_noise_2d)(double x, double y);
|
double (*_func_noise_2d)(double x, double y);
|
||||||
double (*_func_noise_3d)(double x, double y, double z);
|
double (*_func_noise_3d)(double x, double y, double z);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,40 +3,33 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "RandomGenerator.h"
|
#include "RandomGenerator.h"
|
||||||
|
|
||||||
NoiseState::NoiseState()
|
NoiseState::NoiseState() {
|
||||||
{
|
for (int i = 0; i < 30; i++) {
|
||||||
for (int i = 0; i < 30; i++)
|
|
||||||
{
|
|
||||||
level_offsets.push_back(NoiseOffset());
|
level_offsets.push_back(NoiseOffset());
|
||||||
}
|
}
|
||||||
randomizeOffsets();
|
randomizeOffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseState::save(PackStream *stream) const
|
void NoiseState::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int levels = level_offsets.size();
|
int levels = level_offsets.size();
|
||||||
stream->write(&levels);
|
stream->write(&levels);
|
||||||
for (const auto &level_offset:level_offsets)
|
for (const auto &level_offset : level_offsets) {
|
||||||
{
|
|
||||||
stream->write(&level_offset.x);
|
stream->write(&level_offset.x);
|
||||||
stream->write(&level_offset.y);
|
stream->write(&level_offset.y);
|
||||||
stream->write(&level_offset.z);
|
stream->write(&level_offset.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseState::load(PackStream *stream)
|
void NoiseState::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int levels;
|
int levels;
|
||||||
stream->read(&levels);
|
stream->read(&levels);
|
||||||
level_offsets.clear();
|
level_offsets.clear();
|
||||||
|
|
||||||
if (levels > 1000)
|
if (levels > 1000) {
|
||||||
{
|
|
||||||
levels = 1000;
|
levels = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < levels; i++)
|
for (int i = 0; i < levels; i++) {
|
||||||
{
|
|
||||||
NoiseOffset level_offset;
|
NoiseOffset level_offset;
|
||||||
stream->read(&level_offset.x);
|
stream->read(&level_offset.x);
|
||||||
stream->read(&level_offset.y);
|
stream->read(&level_offset.y);
|
||||||
|
@ -45,38 +38,31 @@ void NoiseState::load(PackStream *stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseState::copy(NoiseState *destination) const
|
void NoiseState::copy(NoiseState *destination) const {
|
||||||
{
|
|
||||||
destination->level_offsets = level_offsets;
|
destination->level_offsets = level_offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseState::randomizeOffsets()
|
void NoiseState::randomizeOffsets() {
|
||||||
{
|
for (auto &level_offset : level_offsets) {
|
||||||
for (auto &level_offset:level_offsets)
|
|
||||||
{
|
|
||||||
level_offset.x = RandomGenerator::random();
|
level_offset.x = RandomGenerator::random();
|
||||||
level_offset.y = RandomGenerator::random();
|
level_offset.y = RandomGenerator::random();
|
||||||
level_offset.z = RandomGenerator::random();
|
level_offset.z = RandomGenerator::random();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseState::resetOffsets(double x, double y, double z)
|
void NoiseState::resetOffsets(double x, double y, double z) {
|
||||||
{
|
for (auto &level_offset : level_offsets) {
|
||||||
for (auto &level_offset:level_offsets)
|
|
||||||
{
|
|
||||||
level_offset.x = x;
|
level_offset.x = x;
|
||||||
level_offset.y = y;
|
level_offset.y = y;
|
||||||
level_offset.z = z;
|
level_offset.z = z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseState::setLevel(int level, double x, double y, double z)
|
void NoiseState::setLevel(int level, double x, double y, double z) {
|
||||||
{
|
|
||||||
NoiseOffset offset = {x, y, z};
|
NoiseOffset offset = {x, y, z};
|
||||||
level_offsets.at(level) = offset;
|
level_offsets.at(level) = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseState::setLevelCount(int level_count)
|
void NoiseState::setLevelCount(int level_count) {
|
||||||
{
|
|
||||||
level_offsets.resize(level_count);
|
level_offsets.resize(level_count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,35 +11,33 @@ namespace basics {
|
||||||
*
|
*
|
||||||
* This state contains the noise offsets for noise layers.
|
* This state contains the noise offsets for noise layers.
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT NoiseState
|
class BASICSSHARED_EXPORT NoiseState {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
double z;
|
double z;
|
||||||
} NoiseOffset;
|
} NoiseOffset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NoiseState();
|
NoiseState();
|
||||||
|
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
void copy(NoiseState* destination) const;
|
void copy(NoiseState *destination) const;
|
||||||
|
|
||||||
void randomizeOffsets();
|
void randomizeOffsets();
|
||||||
void resetOffsets(double x=0.0, double y=0.0, double z=0.0);
|
void resetOffsets(double x = 0.0, double y = 0.0, double z = 0.0);
|
||||||
|
|
||||||
void setLevel(int level, double x, double y, double z);
|
void setLevel(int level, double x, double y, double z);
|
||||||
void setLevelCount(int level_count);
|
void setLevelCount(int level_count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<NoiseOffset> level_offsets;
|
std::vector<NoiseOffset> level_offsets;
|
||||||
|
|
||||||
friend class NoiseGenerator;
|
friend class NoiseGenerator;
|
||||||
friend class FractalNoise;
|
friend class FractalNoise;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "SpaceGridIterator.h"
|
#include "SpaceGridIterator.h"
|
||||||
|
|
||||||
SpaceGridIterator::SpaceGridIterator()
|
SpaceGridIterator::SpaceGridIterator() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,8 @@ namespace basics {
|
||||||
*
|
*
|
||||||
* This may be useful for ray marching algorithms for example.
|
* This may be useful for ray marching algorithms for example.
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT SpaceGridIterator
|
class BASICSSHARED_EXPORT SpaceGridIterator {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
SpaceGridIterator();
|
SpaceGridIterator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +22,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool onCell(int x, int y, int z) = 0;
|
virtual bool onCell(int x, int y, int z) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,54 +4,36 @@
|
||||||
#include "SpaceGridIterator.h"
|
#include "SpaceGridIterator.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
SpaceSegment::SpaceSegment(const Vector3& start, const Vector3& end):
|
SpaceSegment::SpaceSegment(const Vector3 &start, const Vector3 &end) : start(start), end(end) {
|
||||||
start(start), end(end)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpaceSegment::intersectYInterval(double ymin, double ymax)
|
bool SpaceSegment::intersectYInterval(double ymin, double ymax) {
|
||||||
{
|
if (start.y > ymax) {
|
||||||
if (start.y > ymax)
|
if (end.y >= ymax) {
|
||||||
{
|
|
||||||
if (end.y >= ymax)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Vector3 diff = end.sub(start);
|
Vector3 diff = end.sub(start);
|
||||||
start = start.add(diff.scale((ymax - start.y) / diff.y));
|
start = start.add(diff.scale((ymax - start.y) / diff.y));
|
||||||
if (end.y < ymin)
|
if (end.y < ymin) {
|
||||||
{
|
|
||||||
end = end.add(diff.scale((ymin - end.y) / diff.y));
|
end = end.add(diff.scale((ymin - end.y) / diff.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (start.y < ymin) {
|
||||||
else if (start.y < ymin)
|
if (end.y <= ymin) {
|
||||||
{
|
|
||||||
if (end.y <= ymin)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Vector3 diff = end.sub(start);
|
Vector3 diff = end.sub(start);
|
||||||
start = start.add(diff.scale((ymin - start.y) / diff.y));
|
start = start.add(diff.scale((ymin - start.y) / diff.y));
|
||||||
if (end.y >= ymax)
|
if (end.y >= ymax) {
|
||||||
{
|
|
||||||
end = end.add(diff.scale((ymax - end.y) / diff.y));
|
end = end.add(diff.scale((ymax - end.y) / diff.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else /* start is inside layer */
|
||||||
else /* start is inside layer */
|
|
||||||
{
|
{
|
||||||
Vector3 diff = end.sub(start);
|
Vector3 diff = end.sub(start);
|
||||||
if (end.y > ymax)
|
if (end.y > ymax) {
|
||||||
{
|
|
||||||
end = start.add(diff.scale((ymax - start.y) / diff.y));
|
end = start.add(diff.scale((ymax - start.y) / diff.y));
|
||||||
}
|
} else if (end.y < ymin) {
|
||||||
else if (end.y < ymin)
|
|
||||||
{
|
|
||||||
end = start.add(diff.scale((ymin - start.y) / diff.y));
|
end = start.add(diff.scale((ymin - start.y) / diff.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,8 +41,7 @@ bool SpaceSegment::intersectYInterval(double ymin, double ymax)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpaceSegment::intersectBoundingBox(const SpaceSegment &bbox) const
|
bool SpaceSegment::intersectBoundingBox(const SpaceSegment &bbox) const {
|
||||||
{
|
|
||||||
Vector3 dir = getDirection();
|
Vector3 dir = getDirection();
|
||||||
// r.dir is unit direction vector of ray
|
// r.dir is unit direction vector of ray
|
||||||
double dfx = 1.0 / dir.x;
|
double dfx = 1.0 / dir.x;
|
||||||
|
@ -80,15 +61,13 @@ bool SpaceSegment::intersectBoundingBox(const SpaceSegment &bbox) const
|
||||||
|
|
||||||
// if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
|
// if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
|
||||||
double t;
|
double t;
|
||||||
if (tmax < 0.0)
|
if (tmax < 0.0) {
|
||||||
{
|
|
||||||
t = tmax;
|
t = tmax;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if tmin > tmax, ray doesn't intersect AABB
|
// if tmin > tmax, ray doesn't intersect AABB
|
||||||
if (tmin > tmax)
|
if (tmin > tmax) {
|
||||||
{
|
|
||||||
t = tmax;
|
t = tmax;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -97,28 +76,23 @@ bool SpaceSegment::intersectBoundingBox(const SpaceSegment &bbox) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceSegment SpaceSegment::projectedOnXPlane(double x) const
|
SpaceSegment SpaceSegment::projectedOnXPlane(double x) const {
|
||||||
{
|
|
||||||
return SpaceSegment(Vector3(x, start.y, start.z), Vector3(x, end.y, end.z));
|
return SpaceSegment(Vector3(x, start.y, start.z), Vector3(x, end.y, end.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceSegment SpaceSegment::projectedOnYPlane(double y) const
|
SpaceSegment SpaceSegment::projectedOnYPlane(double y) const {
|
||||||
{
|
|
||||||
return SpaceSegment(Vector3(start.x, y, start.z), Vector3(end.x, y, end.z));
|
return SpaceSegment(Vector3(start.x, y, start.z), Vector3(end.x, y, end.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceSegment SpaceSegment::projectedOnZPlane(double z) const
|
SpaceSegment SpaceSegment::projectedOnZPlane(double z) const {
|
||||||
{
|
|
||||||
return SpaceSegment(Vector3(start.x, start.y, z), Vector3(end.x, end.y, z));
|
return SpaceSegment(Vector3(start.x, start.y, z), Vector3(end.x, end.y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceSegment SpaceSegment::scaled(double factor) const
|
SpaceSegment SpaceSegment::scaled(double factor) const {
|
||||||
{
|
|
||||||
return SpaceSegment(start.scale(factor), end.scale(factor));
|
return SpaceSegment(start.scale(factor), end.scale(factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpaceSegment::iterateOnGrid(SpaceGridIterator &delegate)
|
bool SpaceSegment::iterateOnGrid(SpaceGridIterator &delegate) {
|
||||||
{
|
|
||||||
Vector3 diff = end.sub(start);
|
Vector3 diff = end.sub(start);
|
||||||
|
|
||||||
int stepX = diff.x < 0.0 ? -1 : 1;
|
int stepX = diff.x < 0.0 ? -1 : 1;
|
||||||
|
@ -137,36 +111,25 @@ bool SpaceSegment::iterateOnGrid(SpaceGridIterator &delegate)
|
||||||
double tMaxY = diff.y == 0.0 ? INFINITY : ((double)(Y + (stepY > 0 ? 1 : 0)) - start.y) / diff.y;
|
double tMaxY = diff.y == 0.0 ? INFINITY : ((double)(Y + (stepY > 0 ? 1 : 0)) - start.y) / diff.y;
|
||||||
double tMaxZ = diff.z == 0.0 ? INFINITY : ((double)(Z + (stepZ > 0 ? 1 : 0)) - start.z) / diff.z;
|
double tMaxZ = diff.z == 0.0 ? INFINITY : ((double)(Z + (stepZ > 0 ? 1 : 0)) - start.z) / diff.z;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
if (not delegate.onCell(X, Y, Z)) {
|
||||||
if (not delegate.onCell(X, Y, Z))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tMaxX < tMaxY)
|
if (tMaxX < tMaxY) {
|
||||||
{
|
if (tMaxX < tMaxZ) {
|
||||||
if (tMaxX < tMaxZ)
|
|
||||||
{
|
|
||||||
X = X + stepX;
|
X = X + stepX;
|
||||||
tMaxX = tMaxX + tDeltaX;
|
tMaxX = tMaxX + tDeltaX;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Z = Z + stepZ;
|
Z = Z + stepZ;
|
||||||
tMaxZ = tMaxZ + tDeltaZ;
|
tMaxZ = tMaxZ + tDeltaZ;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (tMaxY < tMaxZ) {
|
||||||
{
|
|
||||||
if(tMaxY < tMaxZ)
|
|
||||||
{
|
|
||||||
Y = Y + stepY;
|
Y = Y + stepY;
|
||||||
tMaxY = tMaxY + tDeltaY;
|
tMaxY = tMaxY + tDeltaY;
|
||||||
}
|
} else {
|
||||||
else
|
Z = Z + stepZ;
|
||||||
{
|
|
||||||
Z= Z + stepZ;
|
|
||||||
tMaxZ = tMaxZ + tDeltaZ;
|
tMaxZ = tMaxZ + tDeltaZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,20 +11,34 @@ namespace basics {
|
||||||
/**
|
/**
|
||||||
* A delimited segment in 3D space (mainly useful for rays).
|
* A delimited segment in 3D space (mainly useful for rays).
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT SpaceSegment
|
class BASICSSHARED_EXPORT SpaceSegment {
|
||||||
{
|
public:
|
||||||
public:
|
SpaceSegment(const Vector3 &start, const Vector3 &end);
|
||||||
SpaceSegment(const Vector3& start, const Vector3& end);
|
SpaceSegment() : SpaceSegment(Vector3(), Vector3()) {
|
||||||
SpaceSegment(): SpaceSegment(Vector3(), Vector3()) {}
|
}
|
||||||
|
|
||||||
inline const Vector3 &getStart() const {return start;}
|
inline const Vector3 &getStart() const {
|
||||||
inline const Vector3 &getEnd() const {return end;}
|
return start;
|
||||||
inline Vector3 getDirection() const {return end.sub(start);}
|
}
|
||||||
inline double getLength() const {return end.sub(start).getNorm();}
|
inline const Vector3 &getEnd() const {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
inline Vector3 getDirection() const {
|
||||||
|
return end.sub(start);
|
||||||
|
}
|
||||||
|
inline double getLength() const {
|
||||||
|
return end.sub(start).getNorm();
|
||||||
|
}
|
||||||
|
|
||||||
inline double getXDiff() const {return end.x - start.x;}
|
inline double getXDiff() const {
|
||||||
inline double getYDiff() const {return end.y - start.y;}
|
return end.x - start.x;
|
||||||
inline double getZDiff() const {return end.z - start.z;}
|
}
|
||||||
|
inline double getYDiff() const {
|
||||||
|
return end.y - start.y;
|
||||||
|
}
|
||||||
|
inline double getZDiff() const {
|
||||||
|
return end.z - start.z;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep only the intersection with a slice orthogonal to the Y axis.
|
* Keep only the intersection with a slice orthogonal to the Y axis.
|
||||||
|
@ -41,15 +55,15 @@ public:
|
||||||
/**
|
/**
|
||||||
* Return a version of this segment, projected on a X plane.
|
* Return a version of this segment, projected on a X plane.
|
||||||
*/
|
*/
|
||||||
SpaceSegment projectedOnXPlane(double x=0.0) const;
|
SpaceSegment projectedOnXPlane(double x = 0.0) const;
|
||||||
/**
|
/**
|
||||||
* Return a version of this segment, projected on a Y plane.
|
* Return a version of this segment, projected on a Y plane.
|
||||||
*/
|
*/
|
||||||
SpaceSegment projectedOnYPlane(double y=0.0) const;
|
SpaceSegment projectedOnYPlane(double y = 0.0) const;
|
||||||
/**
|
/**
|
||||||
* Return a version of this segment, projected on a Z plane.
|
* Return a version of this segment, projected on a Z plane.
|
||||||
*/
|
*/
|
||||||
SpaceSegment projectedOnZPlane(double z=0.0) const;
|
SpaceSegment projectedOnZPlane(double z = 0.0) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a scaled version of this segment.
|
* Return a scaled version of this segment.
|
||||||
|
@ -69,11 +83,10 @@ public:
|
||||||
*/
|
*/
|
||||||
bool iterateOnGrid(SpaceGridIterator &delegate);
|
bool iterateOnGrid(SpaceGridIterator &delegate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 start;
|
Vector3 start;
|
||||||
Vector3 end;
|
Vector3 end;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,43 +3,32 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "InfiniteRay.h"
|
#include "InfiniteRay.h"
|
||||||
|
|
||||||
Sphere::Sphere()
|
Sphere::Sphere() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sphere::Sphere(const Vector3 ¢er, double radius):
|
Sphere::Sphere(const Vector3 ¢er, double radius) : center(center), radius(radius) {
|
||||||
center(center), radius(radius)
|
|
||||||
{
|
|
||||||
radius2 = radius * radius;
|
radius2 = radius * radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sphere::checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection, Vector3 *second_intersection) const
|
int Sphere::checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection,
|
||||||
{
|
Vector3 *second_intersection) const {
|
||||||
Vector3 L = ray.getOrigin().sub(center);
|
Vector3 L = ray.getOrigin().sub(center);
|
||||||
double b = 2.0 * ray.getDirection().dotProduct(L);
|
double b = 2.0 * ray.getDirection().dotProduct(L);
|
||||||
double c = L.dotProduct(L) - radius2;
|
double c = L.dotProduct(L) - radius2;
|
||||||
|
|
||||||
double discr = b * b - 4.0 * c;
|
double discr = b * b - 4.0 * c;
|
||||||
if (discr < 0)
|
if (discr < 0) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if (discr == 0) {
|
||||||
else if (discr == 0)
|
|
||||||
{
|
|
||||||
*first_intersection = ray.getPointAtCursor(-0.5 * b);
|
*first_intersection = ray.getPointAtCursor(-0.5 * b);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
double x0 = (b > 0.0) ? -0.5 * (b + sqrt(discr)) : -0.5 * (b - sqrt(discr));
|
double x0 = (b > 0.0) ? -0.5 * (b + sqrt(discr)) : -0.5 * (b - sqrt(discr));
|
||||||
double x1 = c / x0;
|
double x1 = c / x0;
|
||||||
if (x0 > x1)
|
if (x0 > x1) {
|
||||||
{
|
|
||||||
*first_intersection = ray.getPointAtCursor(x1);
|
*first_intersection = ray.getPointAtCursor(x1);
|
||||||
*second_intersection = ray.getPointAtCursor(x0);
|
*second_intersection = ray.getPointAtCursor(x0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*first_intersection = ray.getPointAtCursor(x0);
|
*first_intersection = ray.getPointAtCursor(x0);
|
||||||
*second_intersection = ray.getPointAtCursor(x1);
|
*second_intersection = ray.getPointAtCursor(x1);
|
||||||
}
|
}
|
||||||
|
@ -47,15 +36,13 @@ int Sphere::checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sphere::save(PackStream *stream) const
|
void Sphere::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
center.save(stream);
|
center.save(stream);
|
||||||
stream->write(&radius);
|
stream->write(&radius);
|
||||||
stream->write(&radius2);
|
stream->write(&radius2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sphere::load(PackStream *stream)
|
void Sphere::load(PackStream *stream) {
|
||||||
{
|
|
||||||
center.load(stream);
|
center.load(stream);
|
||||||
stream->read(&radius);
|
stream->read(&radius);
|
||||||
stream->read(&radius2);
|
stream->read(&radius2);
|
||||||
|
|
|
@ -11,31 +11,33 @@ namespace basics {
|
||||||
/**
|
/**
|
||||||
* Geometric sphere.
|
* Geometric sphere.
|
||||||
*/
|
*/
|
||||||
class BASICSSHARED_EXPORT Sphere
|
class BASICSSHARED_EXPORT Sphere {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Sphere();
|
Sphere();
|
||||||
Sphere(const Vector3 ¢er, double radius);
|
Sphere(const Vector3 ¢er, double radius);
|
||||||
|
|
||||||
inline const Vector3 &getCenter() const {return center;}
|
inline const Vector3 &getCenter() const {
|
||||||
inline const double &getRadius() const {return radius;}
|
return center;
|
||||||
|
}
|
||||||
|
inline const double &getRadius() const {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the intersection between the sphere and an infinite ray.
|
* Check the intersection between the sphere and an infinite ray.
|
||||||
*
|
*
|
||||||
* Returns the number of intersections (0, 1 or 2) and fill the intersection points.
|
* Returns the number of intersections (0, 1 or 2) and fill the intersection points.
|
||||||
*/
|
*/
|
||||||
int checkRayIntersection(const InfiniteRay& ray, Vector3 *first_intersection, Vector3 *second_intersection) const;
|
int checkRayIntersection(const InfiniteRay &ray, Vector3 *first_intersection, Vector3 *second_intersection) const;
|
||||||
|
|
||||||
void save(PackStream *stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream *stream);
|
void load(PackStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 center;
|
Vector3 center;
|
||||||
double radius;
|
double radius;
|
||||||
double radius2;
|
double radius2;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "PictureWriter.h"
|
#include "PictureWriter.h"
|
||||||
|
|
||||||
Texture2D::Texture2D(int xsize, int ysize)
|
Texture2D::Texture2D(int xsize, int ysize) {
|
||||||
{
|
|
||||||
assert(xsize > 0 && ysize > 0);
|
assert(xsize > 0 && ysize > 0);
|
||||||
|
|
||||||
this->xsize = xsize;
|
this->xsize = xsize;
|
||||||
|
@ -14,39 +13,38 @@ Texture2D::Texture2D(int xsize, int ysize)
|
||||||
this->data = new Color[xsize * ysize];
|
this->data = new Color[xsize * ysize];
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture2D::~Texture2D()
|
Texture2D::~Texture2D() {
|
||||||
{
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::getSize(int* xsize, int* ysize) const
|
void Texture2D::getSize(int *xsize, int *ysize) const {
|
||||||
{
|
|
||||||
*xsize = this->xsize;
|
*xsize = this->xsize;
|
||||||
*ysize = this->ysize;
|
*ysize = this->ysize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::setPixel(int x, int y, Color col)
|
void Texture2D::setPixel(int x, int y, Color col) {
|
||||||
{
|
|
||||||
assert(x >= 0 && x < xsize);
|
assert(x >= 0 && x < xsize);
|
||||||
assert(y >= 0 && y < ysize);
|
assert(y >= 0 && y < ysize);
|
||||||
|
|
||||||
data[y * xsize + x] = col;
|
data[y * xsize + x] = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getPixel(int x, int y) const
|
Color Texture2D::getPixel(int x, int y) const {
|
||||||
{
|
|
||||||
assert(x >= 0 && x < xsize);
|
assert(x >= 0 && x < xsize);
|
||||||
assert(y >= 0 && y < ysize);
|
assert(y >= 0 && y < ysize);
|
||||||
|
|
||||||
return data[y * xsize + x];
|
return data[y * xsize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getNearest(double dx, double dy) const
|
Color Texture2D::getNearest(double dx, double dy) const {
|
||||||
{
|
if (dx < 0.0)
|
||||||
if (dx < 0.0) dx = 0.0;
|
dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0)
|
||||||
if (dy < 0.0) dy = 0.0;
|
dx = 1.0;
|
||||||
if (dy > 1.0) dy = 1.0;
|
if (dy < 0.0)
|
||||||
|
dy = 0.0;
|
||||||
|
if (dy > 1.0)
|
||||||
|
dy = 1.0;
|
||||||
|
|
||||||
int ix = (int)(dx * (double)(this->xsize - 1));
|
int ix = (int)(dx * (double)(this->xsize - 1));
|
||||||
int iy = (int)(dy * (double)(this->ysize - 1));
|
int iy = (int)(dy * (double)(this->ysize - 1));
|
||||||
|
@ -57,31 +55,32 @@ Color Texture2D::getNearest(double dx, double dy) const
|
||||||
return this->data[iy * this->xsize + ix];
|
return this->data[iy * this->xsize + ix];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getLinear(double dx, double dy) const
|
Color Texture2D::getLinear(double dx, double dy) const {
|
||||||
{
|
if (dx < 0.0)
|
||||||
if (dx < 0.0) dx = 0.0;
|
dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0)
|
||||||
if (dy < 0.0) dy = 0.0;
|
dx = 1.0;
|
||||||
if (dy > 1.0) dy = 1.0;
|
if (dy < 0.0)
|
||||||
|
dy = 0.0;
|
||||||
|
if (dy > 1.0)
|
||||||
|
dy = 1.0;
|
||||||
|
|
||||||
dx *= (double)(this->xsize - 1);
|
dx *= (double)(this->xsize - 1);
|
||||||
dy *= (double)(this->ysize - 1);
|
dy *= (double)(this->ysize - 1);
|
||||||
|
|
||||||
int ix = (int)floor(dx);
|
int ix = (int)floor(dx);
|
||||||
if (ix == this->xsize - 1)
|
if (ix == this->xsize - 1) {
|
||||||
{
|
|
||||||
ix--;
|
ix--;
|
||||||
}
|
}
|
||||||
int iy = (int)floor(dy);
|
int iy = (int)floor(dy);
|
||||||
if (iy == this->ysize - 1)
|
if (iy == this->ysize - 1) {
|
||||||
{
|
|
||||||
iy--;
|
iy--;
|
||||||
}
|
}
|
||||||
|
|
||||||
dx -= (double)ix;
|
dx -= (double)ix;
|
||||||
dy -= (double)iy;
|
dy -= (double)iy;
|
||||||
|
|
||||||
Color* data = this->data + iy * this->xsize + ix;
|
Color *data = this->data + iy * this->xsize + ix;
|
||||||
|
|
||||||
Color c1 = data->lerp(*(data + 1), dx);
|
Color c1 = data->lerp(*(data + 1), dx);
|
||||||
Color c2 = (data + this->xsize)->lerp(*(data + this->xsize + 1), dx);
|
Color c2 = (data + this->xsize)->lerp(*(data + this->xsize + 1), dx);
|
||||||
|
@ -89,32 +88,27 @@ Color Texture2D::getLinear(double dx, double dy) const
|
||||||
return c1.lerp(c2, dy);
|
return c1.lerp(c2, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getCubic(double dx, double dy) const
|
Color Texture2D::getCubic(double dx, double dy) const {
|
||||||
{
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return getLinear(dx, dy);
|
return getLinear(dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::fill(Color col)
|
void Texture2D::fill(Color col) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
n = this->xsize * this->ysize;
|
n = this->xsize * this->ysize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
this->data[i] = col;
|
this->data[i] = col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::add(Texture2D* source)
|
void Texture2D::add(Texture2D *source) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
assert(source->xsize == this->xsize);
|
assert(source->xsize == this->xsize);
|
||||||
assert(source->ysize == this->ysize);
|
assert(source->ysize == this->ysize);
|
||||||
|
|
||||||
n = source->xsize * source->ysize;
|
n = source->xsize * source->ysize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
this->data[i].r += source->data[i].r;
|
this->data[i].r += source->data[i].r;
|
||||||
this->data[i].g += source->data[i].g;
|
this->data[i].g += source->data[i].g;
|
||||||
this->data[i].b += source->data[i].b;
|
this->data[i].b += source->data[i].b;
|
||||||
|
@ -122,47 +116,42 @@ void Texture2D::add(Texture2D* source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::save(PackStream* stream) const
|
void Texture2D::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->write(&this->xsize);
|
stream->write(&this->xsize);
|
||||||
stream->write(&this->ysize);
|
stream->write(&this->ysize);
|
||||||
n = this->xsize * this->ysize;
|
n = this->xsize * this->ysize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
(this->data + i)->save(stream);
|
(this->data + i)->save(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::load(PackStream* stream)
|
void Texture2D::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->read(&this->xsize);
|
stream->read(&this->xsize);
|
||||||
stream->read(&this->ysize);
|
stream->read(&this->ysize);
|
||||||
n = this->xsize * this->ysize;
|
n = this->xsize * this->ysize;
|
||||||
delete[] this->data;
|
delete[] this->data;
|
||||||
this->data = new Color[n];
|
this->data = new Color[n];
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
(this->data + i)->load(stream);
|
(this->data + i)->load(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Texture2DWriter:public PictureWriter
|
class Texture2DWriter : public PictureWriter {
|
||||||
{
|
public:
|
||||||
public:
|
Texture2DWriter(const Texture2D *tex) : tex(tex) {
|
||||||
Texture2DWriter(const Texture2D *tex): tex(tex) {}
|
}
|
||||||
|
|
||||||
virtual unsigned int getPixel(int x, int y) override
|
virtual unsigned int getPixel(int x, int y) override {
|
||||||
{
|
|
||||||
return tex->getPixel(x, y).to32BitBGRA();
|
return tex->getPixel(x, y).to32BitBGRA();
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
private:
|
||||||
const Texture2D *tex;
|
const Texture2D *tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Texture2D::saveToFile(const std::string &filepath) const
|
void Texture2D::saveToFile(const std::string &filepath) const {
|
||||||
{
|
|
||||||
Texture2DWriter writer(this);
|
Texture2DWriter writer(this);
|
||||||
writer.save(filepath, xsize, ysize);
|
writer.save(filepath, xsize, ysize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,30 +6,28 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Texture2D
|
class BASICSSHARED_EXPORT Texture2D {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Texture2D(int xsize, int ysize);
|
Texture2D(int xsize, int ysize);
|
||||||
~Texture2D();
|
~Texture2D();
|
||||||
|
|
||||||
void getSize(int* xsize, int* ysize) const;
|
void getSize(int *xsize, int *ysize) const;
|
||||||
void setPixel(int x, int y, Color col);
|
void setPixel(int x, int y, Color col);
|
||||||
Color getPixel(int x, int y) const;
|
Color getPixel(int x, int y) const;
|
||||||
Color getNearest(double dx, double dy) const;
|
Color getNearest(double dx, double dy) const;
|
||||||
Color getLinear(double dx, double dy) const;
|
Color getLinear(double dx, double dy) const;
|
||||||
Color getCubic(double dx, double dy) const;
|
Color getCubic(double dx, double dy) const;
|
||||||
void fill(Color col);
|
void fill(Color col);
|
||||||
void add(Texture2D* other);
|
void add(Texture2D *other);
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
void saveToFile(const std::string &filepath) const;
|
void saveToFile(const std::string &filepath) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int xsize;
|
int xsize;
|
||||||
int ysize;
|
int ysize;
|
||||||
Color* data;
|
Color *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "PictureWriter.h"
|
#include "PictureWriter.h"
|
||||||
|
|
||||||
Texture3D::Texture3D(int xsize, int ysize, int zsize)
|
Texture3D::Texture3D(int xsize, int ysize, int zsize) {
|
||||||
{
|
|
||||||
assert(xsize > 0 && ysize > 0 && zsize > 0);
|
assert(xsize > 0 && ysize > 0 && zsize > 0);
|
||||||
|
|
||||||
this->xsize = xsize;
|
this->xsize = xsize;
|
||||||
|
@ -15,20 +14,17 @@ Texture3D::Texture3D(int xsize, int ysize, int zsize)
|
||||||
this->data = new Color[xsize * ysize * zsize];
|
this->data = new Color[xsize * ysize * zsize];
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture3D::~Texture3D()
|
Texture3D::~Texture3D() {
|
||||||
{
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::getSize(int* xsize, int* ysize, int* zsize) const
|
void Texture3D::getSize(int *xsize, int *ysize, int *zsize) const {
|
||||||
{
|
|
||||||
*xsize = this->xsize;
|
*xsize = this->xsize;
|
||||||
*ysize = this->ysize;
|
*ysize = this->ysize;
|
||||||
*zsize = this->zsize;
|
*zsize = this->zsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::setPixel(int x, int y, int z, Color col)
|
void Texture3D::setPixel(int x, int y, int z, Color col) {
|
||||||
{
|
|
||||||
assert(x >= 0 && x < this->xsize);
|
assert(x >= 0 && x < this->xsize);
|
||||||
assert(y >= 0 && y < this->ysize);
|
assert(y >= 0 && y < this->ysize);
|
||||||
assert(z >= 0 && z < this->ysize);
|
assert(z >= 0 && z < this->ysize);
|
||||||
|
@ -36,8 +32,7 @@ void Texture3D::setPixel(int x, int y, int z, Color col)
|
||||||
this->data[z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
this->data[z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getPixel(int x, int y, int z) const
|
Color Texture3D::getPixel(int x, int y, int z) const {
|
||||||
{
|
|
||||||
assert(x >= 0 && x < this->xsize);
|
assert(x >= 0 && x < this->xsize);
|
||||||
assert(y >= 0 && y < this->ysize);
|
assert(y >= 0 && y < this->ysize);
|
||||||
assert(z >= 0 && z < this->zsize);
|
assert(z >= 0 && z < this->zsize);
|
||||||
|
@ -45,14 +40,19 @@ Color Texture3D::getPixel(int x, int y, int z) const
|
||||||
return this->data[z * this->xsize * this->ysize + y * this->xsize + x];
|
return this->data[z * this->xsize * this->ysize + y * this->xsize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getNearest(double dx, double dy, double dz) const
|
Color Texture3D::getNearest(double dx, double dy, double dz) const {
|
||||||
{
|
if (dx < 0.0)
|
||||||
if (dx < 0.0) dx = 0.0;
|
dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0)
|
||||||
if (dy < 0.0) dy = 0.0;
|
dx = 1.0;
|
||||||
if (dy > 1.0) dy = 1.0;
|
if (dy < 0.0)
|
||||||
if (dz < 0.0) dz = 0.0;
|
dy = 0.0;
|
||||||
if (dz > 1.0) dz = 1.0;
|
if (dy > 1.0)
|
||||||
|
dy = 1.0;
|
||||||
|
if (dz < 0.0)
|
||||||
|
dz = 0.0;
|
||||||
|
if (dz > 1.0)
|
||||||
|
dz = 1.0;
|
||||||
|
|
||||||
int ix = (int)(dx * (double)(this->xsize - 1));
|
int ix = (int)(dx * (double)(this->xsize - 1));
|
||||||
int iy = (int)(dy * (double)(this->ysize - 1));
|
int iy = (int)(dy * (double)(this->ysize - 1));
|
||||||
|
@ -65,32 +65,34 @@ Color Texture3D::getNearest(double dx, double dy, double dz) const
|
||||||
return this->data[iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
return this->data[iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getLinear(double dx, double dy, double dz) const
|
Color Texture3D::getLinear(double dx, double dy, double dz) const {
|
||||||
{
|
if (dx < 0.0)
|
||||||
if (dx < 0.0) dx = 0.0;
|
dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0)
|
||||||
if (dy < 0.0) dy = 0.0;
|
dx = 1.0;
|
||||||
if (dy > 1.0) dy = 1.0;
|
if (dy < 0.0)
|
||||||
if (dz < 0.0) dz = 0.0;
|
dy = 0.0;
|
||||||
if (dz > 1.0) dz = 1.0;
|
if (dy > 1.0)
|
||||||
|
dy = 1.0;
|
||||||
|
if (dz < 0.0)
|
||||||
|
dz = 0.0;
|
||||||
|
if (dz > 1.0)
|
||||||
|
dz = 1.0;
|
||||||
|
|
||||||
dx *= (double)(this->xsize - 1);
|
dx *= (double)(this->xsize - 1);
|
||||||
dy *= (double)(this->ysize - 1);
|
dy *= (double)(this->ysize - 1);
|
||||||
dz *= (double)(this->zsize - 1);
|
dz *= (double)(this->zsize - 1);
|
||||||
|
|
||||||
int ix = (int)floor(dx);
|
int ix = (int)floor(dx);
|
||||||
if (ix == this->xsize - 1)
|
if (ix == this->xsize - 1) {
|
||||||
{
|
|
||||||
ix--;
|
ix--;
|
||||||
}
|
}
|
||||||
int iy = (int)floor(dy);
|
int iy = (int)floor(dy);
|
||||||
if (iy == this->ysize - 1)
|
if (iy == this->ysize - 1) {
|
||||||
{
|
|
||||||
iy--;
|
iy--;
|
||||||
}
|
}
|
||||||
int iz = (int)floor(dz);
|
int iz = (int)floor(dz);
|
||||||
if (iz == this->zsize - 1)
|
if (iz == this->zsize - 1) {
|
||||||
{
|
|
||||||
iz--;
|
iz--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +100,7 @@ Color Texture3D::getLinear(double dx, double dy, double dz) const
|
||||||
dy -= (double)iy;
|
dy -= (double)iy;
|
||||||
dz -= (double)iz;
|
dz -= (double)iz;
|
||||||
|
|
||||||
Color* data = this->data + iz * this->xsize * this->ysize + iy * this->xsize + ix;
|
Color *data = this->data + iz * this->xsize * this->ysize + iy * this->xsize + ix;
|
||||||
|
|
||||||
Color cx1 = data->lerp(*(data + 1), dx);
|
Color cx1 = data->lerp(*(data + 1), dx);
|
||||||
Color cx2 = (data + this->xsize)->lerp(*(data + this->xsize + 1), dx);
|
Color cx2 = (data + this->xsize)->lerp(*(data + this->xsize + 1), dx);
|
||||||
|
@ -112,24 +114,20 @@ Color Texture3D::getLinear(double dx, double dy, double dz) const
|
||||||
return cy1.lerp(cy2, dz);
|
return cy1.lerp(cy2, dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getCubic(double dx, double dy, double dz) const
|
Color Texture3D::getCubic(double dx, double dy, double dz) const {
|
||||||
{
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return getLinear(dx, dy, dz);
|
return getLinear(dx, dy, dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::fill(Color col)
|
void Texture3D::fill(Color col) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
n = this->xsize * this->ysize * this->zsize;
|
n = this->xsize * this->ysize * this->zsize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
this->data[i] = col;
|
this->data[i] = col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::add(Texture3D* source)
|
void Texture3D::add(Texture3D *source) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
assert(source->xsize == this->xsize);
|
assert(source->xsize == this->xsize);
|
||||||
|
@ -137,8 +135,7 @@ void Texture3D::add(Texture3D* source)
|
||||||
assert(source->zsize == this->zsize);
|
assert(source->zsize == this->zsize);
|
||||||
|
|
||||||
n = source->xsize * source->ysize * source->zsize;
|
n = source->xsize * source->ysize * source->zsize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
this->data[i].r += source->data[i].r;
|
this->data[i].r += source->data[i].r;
|
||||||
this->data[i].g += source->data[i].g;
|
this->data[i].g += source->data[i].g;
|
||||||
this->data[i].b += source->data[i].b;
|
this->data[i].b += source->data[i].b;
|
||||||
|
@ -146,21 +143,18 @@ void Texture3D::add(Texture3D* source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::save(PackStream* stream) const
|
void Texture3D::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->write(&this->xsize);
|
stream->write(&this->xsize);
|
||||||
stream->write(&this->ysize);
|
stream->write(&this->ysize);
|
||||||
stream->write(&this->zsize);
|
stream->write(&this->zsize);
|
||||||
n = this->xsize * this->ysize * this->zsize;
|
n = this->xsize * this->ysize * this->zsize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
(this->data + i)->save(stream);
|
(this->data + i)->save(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::load(PackStream* stream)
|
void Texture3D::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->read(&this->xsize);
|
stream->read(&this->xsize);
|
||||||
stream->read(&this->ysize);
|
stream->read(&this->ysize);
|
||||||
|
@ -168,19 +162,17 @@ void Texture3D::load(PackStream* stream)
|
||||||
n = this->xsize * this->ysize * this->zsize;
|
n = this->xsize * this->ysize * this->zsize;
|
||||||
delete[] this->data;
|
delete[] this->data;
|
||||||
this->data = new Color[n];
|
this->data = new Color[n];
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
(this->data + i)->load(stream);
|
(this->data + i)->load(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Texture3DWriter:public PictureWriter
|
class Texture3DWriter : public PictureWriter {
|
||||||
{
|
public:
|
||||||
public:
|
Texture3DWriter(const Texture3D *tex) : tex(tex) {
|
||||||
Texture3DWriter(const Texture3D *tex): tex(tex) {}
|
}
|
||||||
|
|
||||||
virtual unsigned int getPixel(int x, int y) override
|
virtual unsigned int getPixel(int x, int y) override {
|
||||||
{
|
|
||||||
int xsize, ysize, zsize;
|
int xsize, ysize, zsize;
|
||||||
tex->getSize(&xsize, &ysize, &zsize);
|
tex->getSize(&xsize, &ysize, &zsize);
|
||||||
|
|
||||||
|
@ -189,12 +181,12 @@ public:
|
||||||
|
|
||||||
return tex->getPixel(x, y, z).to32BitBGRA();
|
return tex->getPixel(x, y, z).to32BitBGRA();
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
private:
|
||||||
const Texture3D *tex;
|
const Texture3D *tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Texture3D::saveToFile(const std::string &filepath) const
|
void Texture3D::saveToFile(const std::string &filepath) const {
|
||||||
{
|
|
||||||
Texture3DWriter writer(this);
|
Texture3DWriter writer(this);
|
||||||
writer.save(filepath, xsize, ysize * zsize);
|
writer.save(filepath, xsize, ysize * zsize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,31 +6,29 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Texture3D
|
class BASICSSHARED_EXPORT Texture3D {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Texture3D(int xsize, int ysize, int zsize);
|
Texture3D(int xsize, int ysize, int zsize);
|
||||||
~Texture3D();
|
~Texture3D();
|
||||||
|
|
||||||
void getSize(int* xsize, int* ysize, int* zsize) const;
|
void getSize(int *xsize, int *ysize, int *zsize) const;
|
||||||
void setPixel(int x, int y, int z, Color col);
|
void setPixel(int x, int y, int z, Color col);
|
||||||
Color getPixel(int x, int y, int z) const;
|
Color getPixel(int x, int y, int z) const;
|
||||||
Color getNearest(double dx, double dy, double dz) const;
|
Color getNearest(double dx, double dy, double dz) const;
|
||||||
Color getLinear(double dx, double dy, double dz) const;
|
Color getLinear(double dx, double dy, double dz) const;
|
||||||
Color getCubic(double dx, double dy, double dz) const;
|
Color getCubic(double dx, double dy, double dz) const;
|
||||||
void fill(Color col);
|
void fill(Color col);
|
||||||
void add(Texture3D* other);
|
void add(Texture3D *other);
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
void saveToFile(const std::string &filepath) const;
|
void saveToFile(const std::string &filepath) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int xsize;
|
int xsize;
|
||||||
int ysize;
|
int ysize;
|
||||||
int zsize;
|
int zsize;
|
||||||
Color* data;
|
Color *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "PictureWriter.h"
|
#include "PictureWriter.h"
|
||||||
|
|
||||||
Texture4D::Texture4D(int xsize, int ysize, int zsize, int wsize)
|
Texture4D::Texture4D(int xsize, int ysize, int zsize, int wsize) {
|
||||||
{
|
|
||||||
assert(xsize > 0 && ysize > 0 && zsize > 0 && wsize > 0);
|
assert(xsize > 0 && ysize > 0 && zsize > 0 && wsize > 0);
|
||||||
|
|
||||||
this->xsize = xsize;
|
this->xsize = xsize;
|
||||||
|
@ -16,21 +15,18 @@ Texture4D::Texture4D(int xsize, int ysize, int zsize, int wsize)
|
||||||
this->data = new Color[xsize * ysize * zsize * wsize];
|
this->data = new Color[xsize * ysize * zsize * wsize];
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture4D::~Texture4D()
|
Texture4D::~Texture4D() {
|
||||||
{
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::getSize(int* xsize, int* ysize, int* zsize, int* wsize) const
|
void Texture4D::getSize(int *xsize, int *ysize, int *zsize, int *wsize) const {
|
||||||
{
|
|
||||||
*xsize = this->xsize;
|
*xsize = this->xsize;
|
||||||
*ysize = this->ysize;
|
*ysize = this->ysize;
|
||||||
*zsize = this->zsize;
|
*zsize = this->zsize;
|
||||||
*wsize = this->wsize;
|
*wsize = this->wsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::setPixel(int x, int y, int z, int w, Color col)
|
void Texture4D::setPixel(int x, int y, int z, int w, Color col) {
|
||||||
{
|
|
||||||
assert(x >= 0 && x < this->xsize);
|
assert(x >= 0 && x < this->xsize);
|
||||||
assert(y >= 0 && y < this->ysize);
|
assert(y >= 0 && y < this->ysize);
|
||||||
assert(z >= 0 && z < this->zsize);
|
assert(z >= 0 && z < this->zsize);
|
||||||
|
@ -39,26 +35,33 @@ void Texture4D::setPixel(int x, int y, int z, int w, Color col)
|
||||||
this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getPixel(int x, int y, int z, int w) const
|
Color Texture4D::getPixel(int x, int y, int z, int w) const {
|
||||||
{
|
|
||||||
assert(x >= 0 && x < this->xsize);
|
assert(x >= 0 && x < this->xsize);
|
||||||
assert(y >= 0 && y < this->ysize);
|
assert(y >= 0 && y < this->ysize);
|
||||||
assert(z >= 0 && z < this->zsize);
|
assert(z >= 0 && z < this->zsize);
|
||||||
assert(w >= 0 && w < this->wsize);
|
assert(w >= 0 && w < this->wsize);
|
||||||
|
|
||||||
return this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x];
|
return this
|
||||||
|
->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getNearest(double dx, double dy, double dz, double dw) const
|
Color Texture4D::getNearest(double dx, double dy, double dz, double dw) const {
|
||||||
{
|
if (dx < 0.0)
|
||||||
if (dx < 0.0) dx = 0.0;
|
dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0)
|
||||||
if (dy < 0.0) dy = 0.0;
|
dx = 1.0;
|
||||||
if (dy > 1.0) dy = 1.0;
|
if (dy < 0.0)
|
||||||
if (dz < 0.0) dz = 0.0;
|
dy = 0.0;
|
||||||
if (dz > 1.0) dz = 1.0;
|
if (dy > 1.0)
|
||||||
if (dw < 0.0) dw = 0.0;
|
dy = 1.0;
|
||||||
if (dw > 1.0) dw = 1.0;
|
if (dz < 0.0)
|
||||||
|
dz = 0.0;
|
||||||
|
if (dz > 1.0)
|
||||||
|
dz = 1.0;
|
||||||
|
if (dw < 0.0)
|
||||||
|
dw = 0.0;
|
||||||
|
if (dw > 1.0)
|
||||||
|
dw = 1.0;
|
||||||
|
|
||||||
int ix = (int)(dx * (double)(this->xsize - 1));
|
int ix = (int)(dx * (double)(this->xsize - 1));
|
||||||
int iy = (int)(dy * (double)(this->ysize - 1));
|
int iy = (int)(dy * (double)(this->ysize - 1));
|
||||||
|
@ -70,19 +73,27 @@ Color Texture4D::getNearest(double dx, double dy, double dz, double dw) const
|
||||||
assert(iz >= 0 && iz < this->zsize);
|
assert(iz >= 0 && iz < this->zsize);
|
||||||
assert(iw >= 0 && iw < this->wsize);
|
assert(iw >= 0 && iw < this->wsize);
|
||||||
|
|
||||||
return this->data[iw * this->xsize * this->ysize * this->zsize + iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
return this
|
||||||
|
->data[iw * this->xsize * this->ysize * this->zsize + iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getLinear(double dx, double dy, double dz, double dw) const
|
Color Texture4D::getLinear(double dx, double dy, double dz, double dw) const {
|
||||||
{
|
if (dx < 0.0)
|
||||||
if (dx < 0.0) dx = 0.0;
|
dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0)
|
||||||
if (dy < 0.0) dy = 0.0;
|
dx = 1.0;
|
||||||
if (dy > 1.0) dy = 1.0;
|
if (dy < 0.0)
|
||||||
if (dz < 0.0) dz = 0.0;
|
dy = 0.0;
|
||||||
if (dz > 1.0) dz = 1.0;
|
if (dy > 1.0)
|
||||||
if (dw < 0.0) dw = 0.0;
|
dy = 1.0;
|
||||||
if (dw > 1.0) dw = 1.0;
|
if (dz < 0.0)
|
||||||
|
dz = 0.0;
|
||||||
|
if (dz > 1.0)
|
||||||
|
dz = 1.0;
|
||||||
|
if (dw < 0.0)
|
||||||
|
dw = 0.0;
|
||||||
|
if (dw > 1.0)
|
||||||
|
dw = 1.0;
|
||||||
|
|
||||||
dx *= (double)(this->xsize - 1);
|
dx *= (double)(this->xsize - 1);
|
||||||
dy *= (double)(this->ysize - 1);
|
dy *= (double)(this->ysize - 1);
|
||||||
|
@ -90,23 +101,19 @@ Color Texture4D::getLinear(double dx, double dy, double dz, double dw) const
|
||||||
dw *= (double)(this->wsize - 1);
|
dw *= (double)(this->wsize - 1);
|
||||||
|
|
||||||
int ix = (int)floor(dx);
|
int ix = (int)floor(dx);
|
||||||
if (ix == this->xsize - 1)
|
if (ix == this->xsize - 1) {
|
||||||
{
|
|
||||||
ix--;
|
ix--;
|
||||||
}
|
}
|
||||||
int iy = (int)floor(dy);
|
int iy = (int)floor(dy);
|
||||||
if (iy == this->ysize - 1)
|
if (iy == this->ysize - 1) {
|
||||||
{
|
|
||||||
iy--;
|
iy--;
|
||||||
}
|
}
|
||||||
int iz = (int)floor(dz);
|
int iz = (int)floor(dz);
|
||||||
if (iz == this->zsize - 1)
|
if (iz == this->zsize - 1) {
|
||||||
{
|
|
||||||
iz--;
|
iz--;
|
||||||
}
|
}
|
||||||
int iw = (int)floor(dw);
|
int iw = (int)floor(dw);
|
||||||
if (iw == this->wsize - 1)
|
if (iw == this->wsize - 1) {
|
||||||
{
|
|
||||||
iw--;
|
iw--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +122,8 @@ Color Texture4D::getLinear(double dx, double dy, double dz, double dw) const
|
||||||
dz -= (double)iz;
|
dz -= (double)iz;
|
||||||
dw -= (double)iw;
|
dw -= (double)iw;
|
||||||
|
|
||||||
Color* data = this->data + iw * this->xsize * this->ysize * this->zsize + iz * this->xsize * this->ysize + iy * this->xsize + ix;
|
Color *data = this->data + iw * this->xsize * this->ysize * this->zsize + iz * this->xsize * this->ysize +
|
||||||
|
iy * this->xsize + ix;
|
||||||
Color cz1, cz2;
|
Color cz1, cz2;
|
||||||
|
|
||||||
Color cx1 = data->lerp(*(data + 1), dx);
|
Color cx1 = data->lerp(*(data + 1), dx);
|
||||||
|
@ -143,24 +151,20 @@ Color Texture4D::getLinear(double dx, double dy, double dz, double dw) const
|
||||||
return cz1.lerp(cz2, dw);
|
return cz1.lerp(cz2, dw);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getCubic(double dx, double dy, double dz, double dw) const
|
Color Texture4D::getCubic(double dx, double dy, double dz, double dw) const {
|
||||||
{
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return getLinear(dx, dy, dz, dw);
|
return getLinear(dx, dy, dz, dw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::fill(Color col)
|
void Texture4D::fill(Color col) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
n = this->xsize * this->ysize * this->zsize * this->wsize;
|
n = this->xsize * this->ysize * this->zsize * this->wsize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
this->data[i] = col;
|
this->data[i] = col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::add(Texture4D* source)
|
void Texture4D::add(Texture4D *source) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
assert(source->xsize == this->xsize);
|
assert(source->xsize == this->xsize);
|
||||||
|
@ -169,8 +173,7 @@ void Texture4D::add(Texture4D* source)
|
||||||
assert(source->wsize == this->wsize);
|
assert(source->wsize == this->wsize);
|
||||||
|
|
||||||
n = source->xsize * source->ysize * source->zsize * source->wsize;
|
n = source->xsize * source->ysize * source->zsize * source->wsize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
this->data[i].r += source->data[i].r;
|
this->data[i].r += source->data[i].r;
|
||||||
this->data[i].g += source->data[i].g;
|
this->data[i].g += source->data[i].g;
|
||||||
this->data[i].b += source->data[i].b;
|
this->data[i].b += source->data[i].b;
|
||||||
|
@ -178,22 +181,19 @@ void Texture4D::add(Texture4D* source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::save(PackStream* stream) const
|
void Texture4D::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->write(&this->xsize);
|
stream->write(&this->xsize);
|
||||||
stream->write(&this->ysize);
|
stream->write(&this->ysize);
|
||||||
stream->write(&this->zsize);
|
stream->write(&this->zsize);
|
||||||
stream->write(&this->wsize);
|
stream->write(&this->wsize);
|
||||||
n = this->xsize * this->ysize * this->zsize * this->wsize;
|
n = this->xsize * this->ysize * this->zsize * this->wsize;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
(this->data + i)->save(stream);
|
(this->data + i)->save(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::load(PackStream* stream)
|
void Texture4D::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->read(&this->xsize);
|
stream->read(&this->xsize);
|
||||||
stream->read(&this->ysize);
|
stream->read(&this->ysize);
|
||||||
|
@ -202,20 +202,17 @@ void Texture4D::load(PackStream* stream)
|
||||||
n = this->xsize * this->ysize * this->zsize * this->wsize;
|
n = this->xsize * this->ysize * this->zsize * this->wsize;
|
||||||
delete[] this->data;
|
delete[] this->data;
|
||||||
this->data = new Color[n];
|
this->data = new Color[n];
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
(this->data + i)->load(stream);
|
(this->data + i)->load(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Texture4DWriter : public PictureWriter {
|
||||||
|
public:
|
||||||
|
Texture4DWriter(const Texture4D *tex) : tex(tex) {
|
||||||
|
}
|
||||||
|
|
||||||
class Texture4DWriter:public PictureWriter
|
virtual unsigned int getPixel(int x, int y) override {
|
||||||
{
|
|
||||||
public:
|
|
||||||
Texture4DWriter(const Texture4D *tex): tex(tex) {}
|
|
||||||
|
|
||||||
virtual unsigned int getPixel(int x, int y) override
|
|
||||||
{
|
|
||||||
int xsize, ysize, zsize, wsize;
|
int xsize, ysize, zsize, wsize;
|
||||||
tex->getSize(&xsize, &ysize, &zsize, &wsize);
|
tex->getSize(&xsize, &ysize, &zsize, &wsize);
|
||||||
|
|
||||||
|
@ -227,12 +224,12 @@ public:
|
||||||
|
|
||||||
return tex->getPixel(x, y, z, w).to32BitBGRA();
|
return tex->getPixel(x, y, z, w).to32BitBGRA();
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
private:
|
||||||
const Texture4D *tex;
|
const Texture4D *tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Texture4D::saveToFile(const std::string &filepath) const
|
void Texture4D::saveToFile(const std::string &filepath) const {
|
||||||
{
|
|
||||||
Texture4DWriter writer(this);
|
Texture4DWriter writer(this);
|
||||||
writer.save(filepath, xsize * wsize, ysize * zsize);
|
writer.save(filepath, xsize * wsize, ysize * zsize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,32 +6,30 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Texture4D
|
class BASICSSHARED_EXPORT Texture4D {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Texture4D(int xsize, int ysize, int zsize, int wsize);
|
Texture4D(int xsize, int ysize, int zsize, int wsize);
|
||||||
~Texture4D();
|
~Texture4D();
|
||||||
|
|
||||||
void getSize(int* xsize, int* ysize, int* zsize, int* wsize) const;
|
void getSize(int *xsize, int *ysize, int *zsize, int *wsize) const;
|
||||||
void setPixel(int x, int y, int z, int w, Color col);
|
void setPixel(int x, int y, int z, int w, Color col);
|
||||||
Color getPixel(int x, int y, int z, int w) const;
|
Color getPixel(int x, int y, int z, int w) const;
|
||||||
Color getNearest(double dx, double dy, double dz, double dw) const;
|
Color getNearest(double dx, double dy, double dz, double dw) const;
|
||||||
Color getLinear(double dx, double dy, double dz, double dw) const;
|
Color getLinear(double dx, double dy, double dz, double dw) const;
|
||||||
Color getCubic(double dx, double dy, double dz, double dw) const;
|
Color getCubic(double dx, double dy, double dz, double dw) const;
|
||||||
void fill(Color col);
|
void fill(Color col);
|
||||||
void add(Texture4D* other);
|
void add(Texture4D *other);
|
||||||
void save(PackStream* stream) const;
|
void save(PackStream *stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream *stream);
|
||||||
void saveToFile(const std::string &filepath) const;
|
void saveToFile(const std::string &filepath) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int xsize;
|
int xsize;
|
||||||
int ysize;
|
int ysize;
|
||||||
int zsize;
|
int zsize;
|
||||||
int wsize;
|
int wsize;
|
||||||
Color* data;
|
Color *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,41 +12,31 @@ 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_WEST(-1.0, 0.0, 0.0);
|
||||||
const Vector3 paysages::basics::VECTOR_EAST(1.0, 0.0, 0.0);
|
const Vector3 paysages::basics::VECTOR_EAST(1.0, 0.0, 0.0);
|
||||||
|
|
||||||
Vector3::Vector3(const VectorSpherical &v):
|
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))
|
: 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
|
void Vector3::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
stream->write(&x);
|
stream->write(&x);
|
||||||
stream->write(&y);
|
stream->write(&y);
|
||||||
stream->write(&z);
|
stream->write(&z);
|
||||||
}
|
}
|
||||||
void Vector3::load(PackStream* stream)
|
void Vector3::load(PackStream *stream) {
|
||||||
{
|
|
||||||
stream->read(&x);
|
stream->read(&x);
|
||||||
stream->read(&y);
|
stream->read(&y);
|
||||||
stream->read(&z);
|
stream->read(&z);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double _euclidGet2DAngle(double x, double y)
|
static inline double _euclidGet2DAngle(double x, double y) {
|
||||||
{
|
|
||||||
// TEMP Copy of old euclid.c
|
// TEMP Copy of old euclid.c
|
||||||
double nx, ny, d, ret;
|
double nx, ny, d, ret;
|
||||||
|
|
||||||
if (x == 0.0)
|
if (x == 0.0) {
|
||||||
{
|
if (y == 0.0) {
|
||||||
if (y == 0.0)
|
|
||||||
{
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
} else if (y < 0.0) {
|
||||||
else if (y < 0.0)
|
|
||||||
{
|
|
||||||
return 3.0 * M_PI_2;
|
return 3.0 * M_PI_2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return M_PI_2;
|
return M_PI_2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,21 +46,18 @@ static inline double _euclidGet2DAngle(double x, double y)
|
||||||
ny = y / d;
|
ny = y / d;
|
||||||
|
|
||||||
ret = asin(ny);
|
ret = asin(ny);
|
||||||
if (nx < 0.0)
|
if (nx < 0.0) {
|
||||||
{
|
|
||||||
ret = M_PI - ret;
|
ret = M_PI - ret;
|
||||||
}
|
}
|
||||||
return ret < 0.0 ? ret + 2.0 * M_PI : ret;
|
return ret < 0.0 ? ret + 2.0 * M_PI : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorSpherical Vector3::toSpherical() const
|
VectorSpherical Vector3::toSpherical() const {
|
||||||
{
|
|
||||||
VectorSpherical result;
|
VectorSpherical result;
|
||||||
|
|
||||||
result.phi = _euclidGet2DAngle(x, -z);
|
result.phi = _euclidGet2DAngle(x, -z);
|
||||||
result.theta = _euclidGet2DAngle(sqrt(x * x + z * z), y);
|
result.theta = _euclidGet2DAngle(sqrt(x * x + z * z), y);
|
||||||
if (y < 0.0)
|
if (y < 0.0) {
|
||||||
{
|
|
||||||
result.theta -= 2.0 * M_PI;
|
result.theta -= 2.0 * M_PI;
|
||||||
}
|
}
|
||||||
result.r = getNorm();
|
result.r = getNorm();
|
||||||
|
@ -78,19 +65,14 @@ VectorSpherical Vector3::toSpherical() const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::midPointTo(const Vector3 &other) const
|
Vector3 Vector3::midPointTo(const Vector3 &other) const {
|
||||||
{
|
|
||||||
return Vector3((other.x + x) * 0.5, (other.y + y) * 0.5, (other.z + z) * 0.5);
|
return Vector3((other.x + x) * 0.5, (other.y + y) * 0.5, (other.z + z) * 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::randomInSphere(double radius, bool only_surface)
|
Vector3 Vector3::randomInSphere(double radius, bool only_surface) {
|
||||||
{
|
|
||||||
// TODO More uniform spatial repartition
|
// TODO More uniform spatial repartition
|
||||||
// The current randomization clusters result near the center and at the poles
|
// The current randomization clusters result near the center and at the poles
|
||||||
VectorSpherical vec = {
|
VectorSpherical vec = {only_surface ? radius : RandomGenerator::random() * radius,
|
||||||
only_surface ? radius : RandomGenerator::random() * radius,
|
(RandomGenerator::random() - 0.5) * M_PI, RandomGenerator::random() * M_2PI};
|
||||||
(RandomGenerator::random() - 0.5) * M_PI,
|
|
||||||
RandomGenerator::random() * M_2PI
|
|
||||||
};
|
|
||||||
return Vector3(vec);
|
return Vector3(vec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,16 +33,14 @@ namespace basics {
|
||||||
* X=0 Y=-1 Z=0 => THETA=-PI/2
|
* X=0 Y=-1 Z=0 => THETA=-PI/2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
double r;
|
double r;
|
||||||
double theta;
|
double theta;
|
||||||
double phi;
|
double phi;
|
||||||
} VectorSpherical;
|
} VectorSpherical;
|
||||||
|
|
||||||
class BASICSSHARED_EXPORT Vector3
|
class BASICSSHARED_EXPORT Vector3 {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Vector3() = default;
|
Vector3() = default;
|
||||||
Vector3(double x, double y, double z);
|
Vector3(double x, double y, double z);
|
||||||
Vector3(const VectorSpherical &v);
|
Vector3(const VectorSpherical &v);
|
||||||
|
@ -73,9 +71,9 @@ public:
|
||||||
*
|
*
|
||||||
* If *only_surface* is true, produce a vector with *radius* as length.
|
* If *only_surface* is true, produce a vector with *radius* as length.
|
||||||
*/
|
*/
|
||||||
static Vector3 randomInSphere(double radius=1.0, bool only_surface=false);
|
static Vector3 randomInSphere(double radius = 1.0, bool only_surface = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// TODO Make private
|
// TODO Make private
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
|
@ -89,7 +87,6 @@ BASICSSHARED_EXPORT extern const Vector3 VECTOR_NORTH;
|
||||||
BASICSSHARED_EXPORT extern const Vector3 VECTOR_SOUTH;
|
BASICSSHARED_EXPORT extern const Vector3 VECTOR_SOUTH;
|
||||||
BASICSSHARED_EXPORT extern const Vector3 VECTOR_EAST;
|
BASICSSHARED_EXPORT extern const Vector3 VECTOR_EAST;
|
||||||
BASICSSHARED_EXPORT extern const Vector3 VECTOR_WEST;
|
BASICSSHARED_EXPORT extern const Vector3 VECTOR_WEST;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,73 +1,55 @@
|
||||||
#define VECTOR3_INLINE_CPP
|
#define VECTOR3_INLINE_CPP
|
||||||
|
|
||||||
#ifdef VECTOR3_H
|
#ifdef VECTOR3_H
|
||||||
# define METHSPEC inline
|
#define METHSPEC inline
|
||||||
#else
|
#else
|
||||||
# include "Vector3.h"
|
#include "Vector3.h"
|
||||||
# define METHSPEC
|
#define METHSPEC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
METHSPEC Vector3::Vector3(double x, double y, double z):
|
METHSPEC Vector3::Vector3(double x, double y, double z) : x(x), y(y), z(z) {
|
||||||
x(x), y(y), z(z)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Vector3 Vector3::add(double x, double y, double z) const
|
METHSPEC Vector3 Vector3::add(double x, double y, double z) const {
|
||||||
{
|
|
||||||
return Vector3(this->x + x, this->y + y, this->z + z);
|
return Vector3(this->x + x, this->y + y, this->z + z);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Vector3 Vector3::add(const Vector3 &other) const
|
METHSPEC Vector3 Vector3::add(const Vector3 &other) const {
|
||||||
{
|
|
||||||
return Vector3(x + other.x, y + other.y, z + other.z);
|
return Vector3(x + other.x, y + other.y, z + other.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Vector3 Vector3::sub(const Vector3 &other) const
|
METHSPEC Vector3 Vector3::sub(const Vector3 &other) const {
|
||||||
{
|
|
||||||
return Vector3(x - other.x, y - other.y, z - other.z);
|
return Vector3(x - other.x, y - other.y, z - other.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Vector3 Vector3::inverse() const
|
METHSPEC Vector3 Vector3::inverse() const {
|
||||||
{
|
|
||||||
return Vector3(-x, -y, -z);
|
return Vector3(-x, -y, -z);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Vector3 Vector3::scale(double scaling) const
|
METHSPEC Vector3 Vector3::scale(double scaling) const {
|
||||||
{
|
|
||||||
return Vector3(x * scaling, y * scaling, z * scaling);
|
return Vector3(x * scaling, y * scaling, z * scaling);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC double Vector3::getNorm() const
|
METHSPEC double Vector3::getNorm() const {
|
||||||
{
|
|
||||||
return sqrt(x * x + y * y + z * z);
|
return sqrt(x * x + y * y + z * z);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Vector3 Vector3::normalize() const
|
METHSPEC Vector3 Vector3::normalize() const {
|
||||||
{
|
|
||||||
double norm = sqrt(x * x + y * y + z * z);
|
double norm = sqrt(x * x + y * y + z * z);
|
||||||
if (norm == 0.0)
|
if (norm == 0.0) {
|
||||||
{
|
|
||||||
return VECTOR_ZERO;
|
return VECTOR_ZERO;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
norm = 1.0 / norm;
|
norm = 1.0 / norm;
|
||||||
return Vector3(x * norm, y * norm, z * norm);
|
return Vector3(x * norm, y * norm, z * norm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC double Vector3:: dotProduct(const Vector3 &other) const
|
METHSPEC double Vector3::dotProduct(const Vector3 &other) const {
|
||||||
{
|
|
||||||
return x * other.x + y * other.y + z * other.z;
|
return x * other.x + y * other.y + z * other.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHSPEC Vector3 Vector3::crossProduct(const Vector3 &other) const
|
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);
|
||||||
return Vector3(
|
|
||||||
y * other.z - z * other.y,
|
|
||||||
z * other.x - x * other.z,
|
|
||||||
x * other.y - y * other.x
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,33 +3,33 @@
|
||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#if defined(BASICS_LIBRARY)
|
#if defined(BASICS_LIBRARY)
|
||||||
# define BASICSSHARED_EXPORT Q_DECL_EXPORT
|
#define BASICSSHARED_EXPORT Q_DECL_EXPORT
|
||||||
#else
|
#else
|
||||||
# define BASICSSHARED_EXPORT Q_DECL_IMPORT
|
#define BASICSSHARED_EXPORT Q_DECL_IMPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "system_global.h"
|
#include "system_global.h"
|
||||||
|
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
class Vector3;
|
class Vector3;
|
||||||
class Matrix4;
|
class Matrix4;
|
||||||
class BoundingBox;
|
class BoundingBox;
|
||||||
class SpaceGridIterator;
|
class SpaceGridIterator;
|
||||||
class SpaceSegment;
|
class SpaceSegment;
|
||||||
class Color;
|
class Color;
|
||||||
class NoiseGenerator;
|
class NoiseGenerator;
|
||||||
class NoiseState;
|
class NoiseState;
|
||||||
class FractalNoise;
|
class FractalNoise;
|
||||||
class Curve;
|
class Curve;
|
||||||
class ColorProfile;
|
class ColorProfile;
|
||||||
class Texture2D;
|
class Texture2D;
|
||||||
class Texture3D;
|
class Texture3D;
|
||||||
class Texture4D;
|
class Texture4D;
|
||||||
class CappedCylinder;
|
class CappedCylinder;
|
||||||
class InfiniteRay;
|
class InfiniteRay;
|
||||||
class Sphere;
|
class Sphere;
|
||||||
class InfinitePlane;
|
class InfinitePlane;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using namespace paysages::basics;
|
using namespace paysages::basics;
|
||||||
|
|
|
@ -5,24 +5,21 @@
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
#include "GodRaysDefinition.h"
|
#include "GodRaysDefinition.h"
|
||||||
|
|
||||||
AtmosphereDefinition::AtmosphereDefinition(DefinitionNode* parent):
|
AtmosphereDefinition::AtmosphereDefinition(DefinitionNode *parent)
|
||||||
DefinitionNode(parent, "atmosphere", "atmosphere")
|
: DefinitionNode(parent, "atmosphere", "atmosphere") {
|
||||||
{
|
|
||||||
godrays = new GodRaysDefinition(this);
|
godrays = new GodRaysDefinition(this);
|
||||||
daytime = new FloatNode(this, "daytime");
|
daytime = new FloatNode(this, "daytime");
|
||||||
humidity = new FloatNode(this, "humidity");
|
humidity = new FloatNode(this, "humidity");
|
||||||
sun_radius = new FloatNode(this, "sun_radius");
|
sun_radius = new FloatNode(this, "sun_radius");
|
||||||
}
|
}
|
||||||
|
|
||||||
AtmosphereDefinition::~AtmosphereDefinition()
|
AtmosphereDefinition::~AtmosphereDefinition() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::save(PackStream* stream) const
|
void AtmosphereDefinition::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
DefinitionNode::save(stream);
|
DefinitionNode::save(stream);
|
||||||
|
|
||||||
stream->write((int*)&model);
|
stream->write((int *)&model);
|
||||||
sun_color.save(stream);
|
sun_color.save(stream);
|
||||||
stream->write(&dome_lighting);
|
stream->write(&dome_lighting);
|
||||||
stream->write(&moon_radius);
|
stream->write(&moon_radius);
|
||||||
|
@ -31,19 +28,17 @@ void AtmosphereDefinition::save(PackStream* stream) const
|
||||||
|
|
||||||
int star_count = stars.size();
|
int star_count = stars.size();
|
||||||
stream->write(&star_count);
|
stream->write(&star_count);
|
||||||
for (const auto &star : stars)
|
for (const auto &star : stars) {
|
||||||
{
|
|
||||||
star.location.save(stream);
|
star.location.save(stream);
|
||||||
star.col.save(stream);
|
star.col.save(stream);
|
||||||
stream->write(&star.radius);
|
stream->write(&star.radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::load(PackStream* stream)
|
void AtmosphereDefinition::load(PackStream *stream) {
|
||||||
{
|
|
||||||
DefinitionNode::load(stream);
|
DefinitionNode::load(stream);
|
||||||
|
|
||||||
stream->read((int*)&model);
|
stream->read((int *)&model);
|
||||||
sun_color.load(stream);
|
sun_color.load(stream);
|
||||||
stream->read(&dome_lighting);
|
stream->read(&dome_lighting);
|
||||||
stream->read(&moon_radius);
|
stream->read(&moon_radius);
|
||||||
|
@ -52,8 +47,7 @@ void AtmosphereDefinition::load(PackStream* stream)
|
||||||
|
|
||||||
int star_count;
|
int star_count;
|
||||||
stream->read(&star_count);
|
stream->read(&star_count);
|
||||||
for (int i = 0; i < star_count; i++)
|
for (int i = 0; i < star_count; i++) {
|
||||||
{
|
|
||||||
Star star;
|
Star star;
|
||||||
|
|
||||||
star.location.load(stream);
|
star.location.load(stream);
|
||||||
|
@ -66,11 +60,10 @@ void AtmosphereDefinition::load(PackStream* stream)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::copy(DefinitionNode* _destination) const
|
void AtmosphereDefinition::copy(DefinitionNode *_destination) const {
|
||||||
{
|
|
||||||
DefinitionNode::copy(_destination);
|
DefinitionNode::copy(_destination);
|
||||||
|
|
||||||
AtmosphereDefinition* destination = (AtmosphereDefinition*)_destination;
|
AtmosphereDefinition *destination = (AtmosphereDefinition *)_destination;
|
||||||
|
|
||||||
destination->model = model;
|
destination->model = model;
|
||||||
destination->sun_color = sun_color;
|
destination->sun_color = sun_color;
|
||||||
|
@ -83,25 +76,19 @@ void AtmosphereDefinition::copy(DefinitionNode* _destination) const
|
||||||
destination->validate();
|
destination->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::setDayTime(double value)
|
void AtmosphereDefinition::setDayTime(double value) {
|
||||||
{
|
|
||||||
daytime->setValue(value);
|
daytime->setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::setDayTime(int hour, int minute, int second)
|
void AtmosphereDefinition::setDayTime(int hour, int minute, int second) {
|
||||||
{
|
|
||||||
setDayTime((double)hour / 24.0 + (double)minute / 1440.0 + (double)second / 86400.0);
|
setDayTime((double)hour / 24.0 + (double)minute / 1440.0 + (double)second / 86400.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const
|
void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const {
|
||||||
{
|
|
||||||
double value = daytime->getValue();
|
double value = daytime->getValue();
|
||||||
if (value >= 0.0)
|
if (value >= 0.0) {
|
||||||
{
|
|
||||||
value = fmod(value, 1.0);
|
value = fmod(value, 1.0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
value = 1.0 - fmod(-value, 1.0);
|
value = 1.0 - fmod(-value, 1.0);
|
||||||
}
|
}
|
||||||
value *= 86400.0;
|
value *= 86400.0;
|
||||||
|
@ -111,8 +98,7 @@ void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const
|
||||||
*second = value - *minute * 60.0;
|
*second = value - *minute * 60.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::applyPreset(AtmospherePreset preset)
|
void AtmosphereDefinition::applyPreset(AtmospherePreset preset) {
|
||||||
{
|
|
||||||
sun_color.r = 1.0;
|
sun_color.r = 1.0;
|
||||||
sun_color.g = 0.95;
|
sun_color.g = 0.95;
|
||||||
sun_color.b = 0.9;
|
sun_color.b = 0.9;
|
||||||
|
@ -124,8 +110,7 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset)
|
||||||
|
|
||||||
model = ATMOSPHERE_MODEL_BRUNETON;
|
model = ATMOSPHERE_MODEL_BRUNETON;
|
||||||
|
|
||||||
switch (preset)
|
switch (preset) {
|
||||||
{
|
|
||||||
case ATMOSPHERE_PRESET_CLEAR_DAY:
|
case ATMOSPHERE_PRESET_CLEAR_DAY:
|
||||||
setDayTime(15);
|
setDayTime(15);
|
||||||
humidity->setValue(0.1);
|
humidity->setValue(0.1);
|
||||||
|
@ -160,22 +145,22 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::generateStars(int count)
|
void AtmosphereDefinition::generateStars(int count) {
|
||||||
{
|
|
||||||
stars.clear();
|
stars.clear();
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i) {
|
||||||
{
|
|
||||||
Star star;
|
Star star;
|
||||||
|
|
||||||
star.location = Vector3((RandomGenerator::random() - 0.5) * 100000.0, (RandomGenerator::random() * 0.5) * 100000.0, (RandomGenerator::random() - 0.5) * 100000.0);
|
star.location =
|
||||||
if (star.location.getNorm() < 30000.0)
|
Vector3((RandomGenerator::random() - 0.5) * 100000.0, (RandomGenerator::random() * 0.5) * 100000.0,
|
||||||
{
|
(RandomGenerator::random() - 0.5) * 100000.0);
|
||||||
|
if (star.location.getNorm() < 30000.0) {
|
||||||
i--;
|
i--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
double brillance = RandomGenerator::random() * 0.05 + 0.1;
|
double brillance = RandomGenerator::random() * 0.05 + 0.1;
|
||||||
star.col = Color(brillance + RandomGenerator::random() * 0.03, brillance + RandomGenerator::random() * 0.03, brillance + RandomGenerator::random() * 0.03, 1.0);
|
star.col = Color(brillance + RandomGenerator::random() * 0.03, brillance + RandomGenerator::random() * 0.03,
|
||||||
|
brillance + RandomGenerator::random() * 0.03, 1.0);
|
||||||
star.radius = 30.0 + RandomGenerator::random() * 20.0;
|
star.radius = 30.0 + RandomGenerator::random() * 20.0;
|
||||||
|
|
||||||
stars.push_back(star);
|
stars.push_back(star);
|
||||||
|
|
|
@ -11,24 +11,17 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode
|
class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
typedef struct {
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Vector3 location;
|
Vector3 location;
|
||||||
double radius;
|
double radius;
|
||||||
Color col;
|
Color col;
|
||||||
} Star;
|
} Star;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef enum
|
typedef enum { ATMOSPHERE_MODEL_DISABLED = 0, ATMOSPHERE_MODEL_BRUNETON = 1 } AtmosphereModel;
|
||||||
{
|
typedef enum {
|
||||||
ATMOSPHERE_MODEL_DISABLED = 0,
|
|
||||||
ATMOSPHERE_MODEL_BRUNETON = 1
|
|
||||||
} AtmosphereModel;
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ATMOSPHERE_PRESET_CLEAR_DAY = 0,
|
ATMOSPHERE_PRESET_CLEAR_DAY = 0,
|
||||||
ATMOSPHERE_PRESET_CLEAR_SUNSET = 1,
|
ATMOSPHERE_PRESET_CLEAR_SUNSET = 1,
|
||||||
ATMOSPHERE_PRESET_HAZY_MORNING = 2,
|
ATMOSPHERE_PRESET_HAZY_MORNING = 2,
|
||||||
|
@ -36,19 +29,27 @@ public:
|
||||||
ATMOSPHERE_PRESET_STORMY = 4
|
ATMOSPHERE_PRESET_STORMY = 4
|
||||||
} AtmospherePreset;
|
} AtmospherePreset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AtmosphereDefinition(DefinitionNode* parent);
|
AtmosphereDefinition(DefinitionNode *parent);
|
||||||
virtual ~AtmosphereDefinition();
|
virtual ~AtmosphereDefinition();
|
||||||
|
|
||||||
virtual void save(PackStream* stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream* stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
|
|
||||||
virtual void copy(DefinitionNode* destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
|
|
||||||
inline GodRaysDefinition *childGodRays() const {return godrays;}
|
inline GodRaysDefinition *childGodRays() const {
|
||||||
inline FloatNode *propDayTime() const {return daytime;}
|
return godrays;
|
||||||
inline FloatNode *propHumidity() const {return humidity;}
|
}
|
||||||
inline FloatNode *propSunRadius() const {return sun_radius;}
|
inline FloatNode *propDayTime() const {
|
||||||
|
return daytime;
|
||||||
|
}
|
||||||
|
inline FloatNode *propHumidity() const {
|
||||||
|
return humidity;
|
||||||
|
}
|
||||||
|
inline FloatNode *propSunRadius() const {
|
||||||
|
return sun_radius;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the daytime from a 0.0-1.0 value.
|
* Set the daytime from a 0.0-1.0 value.
|
||||||
|
@ -57,7 +58,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Set the daytime from hour/minute/second info.
|
* Set the daytime from hour/minute/second info.
|
||||||
*/
|
*/
|
||||||
void setDayTime(int hour, int minute=0, int second=0);
|
void setDayTime(int hour, int minute = 0, int second = 0);
|
||||||
/**
|
/**
|
||||||
* Get the daytime info, in hour/minute/second.
|
* Get the daytime info, in hour/minute/second.
|
||||||
*/
|
*/
|
||||||
|
@ -66,7 +67,7 @@ public:
|
||||||
void applyPreset(AtmospherePreset preset);
|
void applyPreset(AtmospherePreset preset);
|
||||||
void generateStars(int count);
|
void generateStars(int count);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AtmosphereModel model;
|
AtmosphereModel model;
|
||||||
|
|
||||||
Color sun_color;
|
Color sun_color;
|
||||||
|
@ -78,13 +79,12 @@ public:
|
||||||
|
|
||||||
std::vector<Star> stars;
|
std::vector<Star> stars;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GodRaysDefinition *godrays;
|
GodRaysDefinition *godrays;
|
||||||
FloatNode *humidity;
|
FloatNode *humidity;
|
||||||
FloatNode *daytime;
|
FloatNode *daytime;
|
||||||
FloatNode *sun_radius;
|
FloatNode *sun_radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "BoundingBox.h"
|
#include "BoundingBox.h"
|
||||||
|
|
||||||
CameraDefinition::CameraDefinition(DefinitionNode *parent):
|
CameraDefinition::CameraDefinition(DefinitionNode *parent) : DefinitionNode(parent, "camera", "camera") {
|
||||||
DefinitionNode(parent, "camera", "camera")
|
|
||||||
{
|
|
||||||
location.x = 0.0;
|
location.x = 0.0;
|
||||||
location.y = 0.0;
|
location.y = 0.0;
|
||||||
location.z = 0.0;
|
location.z = 0.0;
|
||||||
|
@ -25,8 +23,7 @@ CameraDefinition::CameraDefinition(DefinitionNode *parent):
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::save(PackStream* stream) const
|
void CameraDefinition::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
location.save(stream);
|
location.save(stream);
|
||||||
stream->write(&direction.r);
|
stream->write(&direction.r);
|
||||||
stream->write(&direction.phi);
|
stream->write(&direction.phi);
|
||||||
|
@ -35,8 +32,7 @@ void CameraDefinition::save(PackStream* stream) const
|
||||||
stream->write(&perspective.yfov);
|
stream->write(&perspective.yfov);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::load(PackStream* stream)
|
void CameraDefinition::load(PackStream *stream) {
|
||||||
{
|
|
||||||
location.load(stream);
|
location.load(stream);
|
||||||
stream->read(&direction.r);
|
stream->read(&direction.r);
|
||||||
stream->read(&direction.phi);
|
stream->read(&direction.phi);
|
||||||
|
@ -47,9 +43,8 @@ void CameraDefinition::load(PackStream* stream)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::copy(DefinitionNode* _destination) const
|
void CameraDefinition::copy(DefinitionNode *_destination) const {
|
||||||
{
|
CameraDefinition *destination = (CameraDefinition *)_destination;
|
||||||
CameraDefinition* destination = (CameraDefinition*)_destination;
|
|
||||||
|
|
||||||
destination->location = location;
|
destination->location = location;
|
||||||
destination->direction = direction;
|
destination->direction = direction;
|
||||||
|
@ -60,10 +55,8 @@ void CameraDefinition::copy(DefinitionNode* _destination) const
|
||||||
destination->validate();
|
destination->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::validate()
|
void CameraDefinition::validate() {
|
||||||
{
|
if (location.y > 300.0) {
|
||||||
if (location.y > 300.0)
|
|
||||||
{
|
|
||||||
location.y = 300.0;
|
location.y = 300.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +78,8 @@ void CameraDefinition::validate()
|
||||||
|
|
||||||
target = location.add(direction);
|
target = location.add(direction);
|
||||||
|
|
||||||
Matrix4 mperspective = Matrix4::newPerspective(perspective.yfov, perspective.xratio, perspective.znear, perspective.zfar);
|
Matrix4 mperspective =
|
||||||
|
Matrix4::newPerspective(perspective.yfov, perspective.xratio, perspective.znear, perspective.zfar);
|
||||||
unperspective = mperspective.inversed();
|
unperspective = mperspective.inversed();
|
||||||
|
|
||||||
projector = mperspective.mult(Matrix4::newLookAt(location, target, up));
|
projector = mperspective.mult(Matrix4::newLookAt(location, target, up));
|
||||||
|
@ -95,33 +89,28 @@ void CameraDefinition::validate()
|
||||||
inv_y_factor = 1.0 / (0.5 * height);
|
inv_y_factor = 1.0 / (0.5 * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
double CameraDefinition::getRealDepth(const Vector3 &projected) const
|
double CameraDefinition::getRealDepth(const Vector3 &projected) const {
|
||||||
{
|
|
||||||
Vector3 v(projected.x * inv_x_factor - 1.0, -(projected.y * inv_x_factor - 1.0), projected.z);
|
Vector3 v(projected.x * inv_x_factor - 1.0, -(projected.y * inv_x_factor - 1.0), projected.z);
|
||||||
return unperspective.transform(v).z;
|
return unperspective.transform(v).z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setLocation(const Vector3 &location)
|
void CameraDefinition::setLocation(const Vector3 &location) {
|
||||||
{
|
|
||||||
this->location = location;
|
this->location = location;
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setLocationCoords(double x, double y, double z)
|
void CameraDefinition::setLocationCoords(double x, double y, double z) {
|
||||||
{
|
|
||||||
location = Vector3(x, y, z);
|
location = Vector3(x, y, z);
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setTarget(const Vector3 &target)
|
void CameraDefinition::setTarget(const Vector3 &target) {
|
||||||
{
|
|
||||||
Vector3 forward;
|
Vector3 forward;
|
||||||
|
|
||||||
forward = target.sub(location);
|
forward = target.sub(location);
|
||||||
if (forward.getNorm() < 0.0000001)
|
if (forward.getNorm() < 0.0000001) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,77 +119,66 @@ void CameraDefinition::setTarget(const Vector3 &target)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setTargetCoords(double x, double y, double z)
|
void CameraDefinition::setTargetCoords(double x, double y, double z) {
|
||||||
{
|
|
||||||
setTarget(Vector3(x, y, z));
|
setTarget(Vector3(x, y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setRoll(double angle)
|
void CameraDefinition::setRoll(double angle) {
|
||||||
{
|
|
||||||
roll = angle;
|
roll = angle;
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setZoomToTarget(double zoom)
|
void CameraDefinition::setZoomToTarget(double zoom) {
|
||||||
{
|
|
||||||
direction.r = zoom;
|
direction.r = zoom;
|
||||||
location = target.add(Vector3(direction).scale(-1.0));
|
location = target.add(Vector3(direction).scale(-1.0));
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setFov(double fov)
|
void CameraDefinition::setFov(double fov) {
|
||||||
{
|
|
||||||
perspective.yfov = fov;
|
perspective.yfov = fov;
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::strafeForward(double value)
|
void CameraDefinition::strafeForward(double value) {
|
||||||
{
|
|
||||||
location = location.add(forward.scale(value));
|
location = location.add(forward.scale(value));
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::strafeRight(double value)
|
void CameraDefinition::strafeRight(double value) {
|
||||||
{
|
|
||||||
location = location.add(right.scale(value));
|
location = location.add(right.scale(value));
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::strafeUp(double value)
|
void CameraDefinition::strafeUp(double value) {
|
||||||
{
|
|
||||||
location = location.add(up.scale(value));
|
location = location.add(up.scale(value));
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::rotateYaw(double value)
|
void CameraDefinition::rotateYaw(double value) {
|
||||||
{
|
|
||||||
direction.phi += value;
|
direction.phi += value;
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::rotatePitch(double value)
|
void CameraDefinition::rotatePitch(double value) {
|
||||||
{
|
|
||||||
direction.theta += value;
|
direction.theta += value;
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::rotateRoll(double value)
|
void CameraDefinition::rotateRoll(double value) {
|
||||||
{
|
|
||||||
roll += value;
|
roll += value;
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraDefinition::setRenderSize(int width, int height)
|
void CameraDefinition::setRenderSize(int width, int height) {
|
||||||
{
|
|
||||||
this->width = (double)width;
|
this->width = (double)width;
|
||||||
this->height = (double)height;
|
this->height = (double)height;
|
||||||
perspective.xratio = this->width / this->height;
|
perspective.xratio = this->width / this->height;
|
||||||
|
@ -208,11 +186,9 @@ void CameraDefinition::setRenderSize(int width, int height)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 CameraDefinition::project(const Vector3 &point) const
|
Vector3 CameraDefinition::project(const Vector3 &point) const {
|
||||||
{
|
|
||||||
Vector3 tpoint = projector.transform(point);
|
Vector3 tpoint = projector.transform(point);
|
||||||
if (tpoint.z < 1.0)
|
if (tpoint.z < 1.0) {
|
||||||
{
|
|
||||||
tpoint.x = -tpoint.x;
|
tpoint.x = -tpoint.x;
|
||||||
tpoint.y = -tpoint.y;
|
tpoint.y = -tpoint.y;
|
||||||
}
|
}
|
||||||
|
@ -221,19 +197,16 @@ Vector3 CameraDefinition::project(const Vector3 &point) const
|
||||||
return tpoint;
|
return tpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 CameraDefinition::unproject(const Vector3 &point) const
|
Vector3 CameraDefinition::unproject(const Vector3 &point) const {
|
||||||
{
|
|
||||||
Vector3 tpoint(point.x / (0.5 * width) - 1.0, -(point.y / (0.5 * height) - 1.0), point.z);
|
Vector3 tpoint(point.x / (0.5 * width) - 1.0, -(point.y / (0.5 * height) - 1.0), point.z);
|
||||||
if (tpoint.z < 1.0)
|
if (tpoint.z < 1.0) {
|
||||||
{
|
|
||||||
tpoint.x = -tpoint.x;
|
tpoint.x = -tpoint.x;
|
||||||
tpoint.y = -tpoint.y;
|
tpoint.y = -tpoint.y;
|
||||||
}
|
}
|
||||||
return unprojector.transform(tpoint);
|
return unprojector.transform(tpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CameraDefinition::isBoxInView(const Vector3 ¢er, double xsize, double ysize, double zsize) const
|
int CameraDefinition::isBoxInView(const Vector3 ¢er, double xsize, double ysize, double zsize) const {
|
||||||
{
|
|
||||||
BoundingBox box;
|
BoundingBox box;
|
||||||
|
|
||||||
box.pushPoint(center.add(Vector3(-xsize, -ysize, -zsize)));
|
box.pushPoint(center.add(Vector3(-xsize, -ysize, -zsize)));
|
||||||
|
@ -242,8 +215,7 @@ int CameraDefinition::isBoxInView(const Vector3 ¢er, double xsize, double ys
|
||||||
return isUnprojectedBoxInView(box);
|
return isUnprojectedBoxInView(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CameraDefinition::isUnprojectedBoxInView(const BoundingBox &box) const
|
int CameraDefinition::isUnprojectedBoxInView(const BoundingBox &box) const {
|
||||||
{
|
|
||||||
BoundingBox projected;
|
BoundingBox projected;
|
||||||
|
|
||||||
projected.pushPoint(project(Vector3(box.xmin, box.ymin, box.zmin)));
|
projected.pushPoint(project(Vector3(box.xmin, box.ymin, box.zmin)));
|
||||||
|
@ -258,23 +230,19 @@ int CameraDefinition::isUnprojectedBoxInView(const BoundingBox &box) const
|
||||||
return isProjectedBoxInView(projected);
|
return isProjectedBoxInView(projected);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CameraDefinition::isProjectedBoxInView(const BoundingBox &box) const
|
int CameraDefinition::isProjectedBoxInView(const BoundingBox &box) const {
|
||||||
{
|
if (box.xmin <= width && box.xmax >= 0.0 && box.ymin <= height && box.ymax >= 0.0 &&
|
||||||
if (box.xmin <= width && box.xmax >= 0.0 && box.ymin <= height && box.ymax >= 0.0 && box.zmax >= perspective.znear)
|
box.zmax >= perspective.znear) {
|
||||||
{
|
|
||||||
double dx = box.xmax - box.xmin;
|
double dx = box.xmax - box.xmin;
|
||||||
double dy = box.ymax - box.ymin;
|
double dy = box.ymax - box.ymin;
|
||||||
|
|
||||||
return (int)ceil(dx) * (int)ceil(dy);
|
return (int)ceil(dx) * (int)ceil(dy);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CameraDefinition::transitionToAnother(const CameraDefinition *wanted, double factor)
|
bool CameraDefinition::transitionToAnother(const CameraDefinition *wanted, double factor) {
|
||||||
{
|
|
||||||
double dx, dy, dz, dr, dphi, dtheta, droll;
|
double dx, dy, dz, dr, dphi, dtheta, droll;
|
||||||
|
|
||||||
dx = wanted->location.x - location.x;
|
dx = wanted->location.x - location.x;
|
||||||
|
@ -285,12 +253,10 @@ bool CameraDefinition::transitionToAnother(const CameraDefinition *wanted, doubl
|
||||||
dtheta = wanted->direction.theta - direction.theta;
|
dtheta = wanted->direction.theta - direction.theta;
|
||||||
droll = wanted->roll - roll;
|
droll = wanted->roll - roll;
|
||||||
|
|
||||||
if (fabs(dx) < 0.000001 && fabs(dy) < 0.000001 && fabs(dz) < 0.000001 && fabs(dr) < 0.000001 && fabs(dphi) < 0.000001 && fabs(dtheta) < 0.000001 && fabs(droll) < 0.000001)
|
if (fabs(dx) < 0.000001 && fabs(dy) < 0.000001 && fabs(dz) < 0.000001 && fabs(dr) < 0.000001 &&
|
||||||
{
|
fabs(dphi) < 0.000001 && fabs(dtheta) < 0.000001 && fabs(droll) < 0.000001) {
|
||||||
return false;
|
return false;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
location.x += dx * factor;
|
location.x += dx * factor;
|
||||||
location.y += dy * factor;
|
location.y += dy * factor;
|
||||||
location.z += dz * factor;
|
location.z += dz * factor;
|
||||||
|
|
|
@ -11,36 +11,56 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
double yfov;
|
double yfov;
|
||||||
double xratio;
|
double xratio;
|
||||||
double znear;
|
double znear;
|
||||||
double zfar;
|
double zfar;
|
||||||
} CameraPerspective;
|
} CameraPerspective;
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT CameraDefinition: public DefinitionNode
|
class DEFINITIONSHARED_EXPORT CameraDefinition : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
CameraDefinition(DefinitionNode *parent = NULL);
|
CameraDefinition(DefinitionNode *parent = NULL);
|
||||||
|
|
||||||
virtual void save(PackStream* pack) const override;
|
virtual void save(PackStream *pack) const override;
|
||||||
virtual void load(PackStream* pack) override;
|
virtual void load(PackStream *pack) override;
|
||||||
|
|
||||||
virtual void copy(DefinitionNode* destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
virtual void validate() override;
|
virtual void validate() override;
|
||||||
|
|
||||||
inline const Vector3 &getLocation() const {return location;}
|
inline const Vector3 &getLocation() const {
|
||||||
inline const Vector3 &getTarget() const {return target;}
|
return location;
|
||||||
inline const Vector3 &getUpVector() const {return up;}
|
}
|
||||||
inline double getRoll() const {return roll;}
|
inline const Vector3 &getTarget() const {
|
||||||
inline Vector3 getDirection() const {return Vector3(direction);}
|
return target;
|
||||||
inline const Vector3 &getDirectionNormalized() const {return forward;}
|
}
|
||||||
inline const Matrix4 &getTransformationMatrix() const {return projector;}
|
inline const Vector3 &getUpVector() const {
|
||||||
inline const VectorSpherical &getDirectionSpherical() const {return direction;}
|
return up;
|
||||||
inline const CameraPerspective &getPerspective() const {return perspective;}
|
}
|
||||||
inline double getWidth() const {return width;}
|
inline double getRoll() const {
|
||||||
inline double getHeight() const {return height;}
|
return roll;
|
||||||
|
}
|
||||||
|
inline Vector3 getDirection() const {
|
||||||
|
return Vector3(direction);
|
||||||
|
}
|
||||||
|
inline const Vector3 &getDirectionNormalized() const {
|
||||||
|
return forward;
|
||||||
|
}
|
||||||
|
inline const Matrix4 &getTransformationMatrix() const {
|
||||||
|
return projector;
|
||||||
|
}
|
||||||
|
inline const VectorSpherical &getDirectionSpherical() const {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
inline const CameraPerspective &getPerspective() const {
|
||||||
|
return perspective;
|
||||||
|
}
|
||||||
|
inline double getWidth() const {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
inline double getHeight() const {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
double getRealDepth(const Vector3 &projected) const;
|
double getRealDepth(const Vector3 &projected) const;
|
||||||
|
|
||||||
|
@ -68,7 +88,7 @@ public:
|
||||||
|
|
||||||
bool transitionToAnother(const CameraDefinition *wanted, double factor);
|
bool transitionToAnother(const CameraDefinition *wanted, double factor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* Definition */
|
/* Definition */
|
||||||
Vector3 location;
|
Vector3 location;
|
||||||
VectorSpherical direction;
|
VectorSpherical direction;
|
||||||
|
@ -90,7 +110,6 @@ private:
|
||||||
double inv_x_factor;
|
double inv_x_factor;
|
||||||
double inv_y_factor;
|
double inv_y_factor;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,7 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
|
|
||||||
CloudLayerDefinition::CloudLayerDefinition(DefinitionNode* parent):
|
CloudLayerDefinition::CloudLayerDefinition(DefinitionNode *parent) : DefinitionNode(parent, "layer", "cloudlayer") {
|
||||||
DefinitionNode(parent, "layer", "cloudlayer")
|
|
||||||
{
|
|
||||||
type = CIRRUS;
|
type = CIRRUS;
|
||||||
altitude = 0.5;
|
altitude = 0.5;
|
||||||
scaling = 0.5;
|
scaling = 0.5;
|
||||||
|
@ -18,26 +16,22 @@ CloudLayerDefinition::CloudLayerDefinition(DefinitionNode* parent):
|
||||||
zoffset = new FloatNode(this, "zoffset");
|
zoffset = new FloatNode(this, "zoffset");
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudLayerDefinition::~CloudLayerDefinition()
|
CloudLayerDefinition::~CloudLayerDefinition() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudLayerDefinition* CloudLayerDefinition::newCopy(const CloudLayerDefinition& other, DefinitionNode* parent)
|
CloudLayerDefinition *CloudLayerDefinition::newCopy(const CloudLayerDefinition &other, DefinitionNode *parent) {
|
||||||
{
|
CloudLayerDefinition *layer = new CloudLayerDefinition(parent);
|
||||||
CloudLayerDefinition* layer = new CloudLayerDefinition(parent);
|
|
||||||
other.copy(layer);
|
other.copy(layer);
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudLayerDefinition* CloudLayerDefinition::newCopy(DefinitionNode* parent) const
|
CloudLayerDefinition *CloudLayerDefinition::newCopy(DefinitionNode *parent) const {
|
||||||
{
|
CloudLayerDefinition *layer = new CloudLayerDefinition(parent);
|
||||||
CloudLayerDefinition* layer = new CloudLayerDefinition(parent);
|
|
||||||
copy(layer);
|
copy(layer);
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudLayerDefinition::save(PackStream* stream) const
|
void CloudLayerDefinition::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
DefinitionNode::save(stream);
|
DefinitionNode::save(stream);
|
||||||
|
|
||||||
int clouds_type = (int)type;
|
int clouds_type = (int)type;
|
||||||
|
@ -50,8 +44,7 @@ void CloudLayerDefinition::save(PackStream* stream) const
|
||||||
noise_state.save(stream);
|
noise_state.save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudLayerDefinition::load(PackStream* stream)
|
void CloudLayerDefinition::load(PackStream *stream) {
|
||||||
{
|
|
||||||
DefinitionNode::load(stream);
|
DefinitionNode::load(stream);
|
||||||
|
|
||||||
int clouds_type;
|
int clouds_type;
|
||||||
|
@ -67,11 +60,10 @@ void CloudLayerDefinition::load(PackStream* stream)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudLayerDefinition::copy(DefinitionNode* _destination) const
|
void CloudLayerDefinition::copy(DefinitionNode *_destination) const {
|
||||||
{
|
|
||||||
DefinitionNode::copy(_destination);
|
DefinitionNode::copy(_destination);
|
||||||
|
|
||||||
CloudLayerDefinition* destination = (CloudLayerDefinition*)_destination;
|
CloudLayerDefinition *destination = (CloudLayerDefinition *)_destination;
|
||||||
|
|
||||||
destination->type = type;
|
destination->type = type;
|
||||||
destination->altitude = altitude;
|
destination->altitude = altitude;
|
||||||
|
@ -81,12 +73,10 @@ void CloudLayerDefinition::copy(DefinitionNode* _destination) const
|
||||||
noise_state.copy(&destination->noise_state);
|
noise_state.copy(&destination->noise_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudLayerDefinition::validate()
|
void CloudLayerDefinition::validate() {
|
||||||
{
|
|
||||||
DefinitionNode::validate();
|
DefinitionNode::validate();
|
||||||
|
|
||||||
if (scaling < 0.1)
|
if (scaling < 0.1) {
|
||||||
{
|
|
||||||
scaling = 0.1;
|
scaling = 0.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,28 +10,32 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT CloudLayerDefinition : public DefinitionNode
|
class DEFINITIONSHARED_EXPORT CloudLayerDefinition : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
CloudLayerDefinition(DefinitionNode *parent);
|
||||||
CloudLayerDefinition(DefinitionNode* parent);
|
|
||||||
virtual ~CloudLayerDefinition();
|
virtual ~CloudLayerDefinition();
|
||||||
|
|
||||||
inline const NoiseState &getNoiseState() const {return noise_state;}
|
inline const NoiseState &getNoiseState() const {
|
||||||
inline FloatNode *propXOffset() const {return xoffset;}
|
return noise_state;
|
||||||
inline FloatNode *propZOffset() const {return zoffset;}
|
}
|
||||||
|
inline FloatNode *propXOffset() const {
|
||||||
|
return xoffset;
|
||||||
|
}
|
||||||
|
inline FloatNode *propZOffset() const {
|
||||||
|
return zoffset;
|
||||||
|
}
|
||||||
|
|
||||||
static CloudLayerDefinition* newCopy(const CloudLayerDefinition& other, DefinitionNode* parent);
|
static CloudLayerDefinition *newCopy(const CloudLayerDefinition &other, DefinitionNode *parent);
|
||||||
CloudLayerDefinition* newCopy(DefinitionNode* parent) const;
|
CloudLayerDefinition *newCopy(DefinitionNode *parent) const;
|
||||||
|
|
||||||
virtual void save(PackStream* pack) const override;
|
virtual void save(PackStream *pack) const override;
|
||||||
virtual void load(PackStream* pack) override;
|
virtual void load(PackStream *pack) override;
|
||||||
|
|
||||||
virtual void copy(DefinitionNode* destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
virtual void validate() override;
|
virtual void validate() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
|
||||||
STRATUS,
|
STRATUS,
|
||||||
NIMBOSTRATUS,
|
NIMBOSTRATUS,
|
||||||
CUMULUS,
|
CUMULUS,
|
||||||
|
@ -44,18 +48,17 @@ public:
|
||||||
CIRRUS
|
CIRRUS
|
||||||
} CloudsType;
|
} CloudsType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CloudsType type;
|
CloudsType type;
|
||||||
NoiseState noise_state;
|
NoiseState noise_state;
|
||||||
double altitude;
|
double altitude;
|
||||||
double scaling;
|
double scaling;
|
||||||
double coverage;
|
double coverage;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FloatNode *xoffset;
|
FloatNode *xoffset;
|
||||||
FloatNode *zoffset;
|
FloatNode *zoffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,18 @@
|
||||||
|
|
||||||
#include "CloudLayerDefinition.h"
|
#include "CloudLayerDefinition.h"
|
||||||
|
|
||||||
static DefinitionNode* _layerConstructor(Layers* parent)
|
static DefinitionNode *_layerConstructor(Layers *parent) {
|
||||||
{
|
|
||||||
return new CloudLayerDefinition(parent);
|
return new CloudLayerDefinition(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudsDefinition::CloudsDefinition(DefinitionNode* parent):
|
CloudsDefinition::CloudsDefinition(DefinitionNode *parent) : Layers(parent, "clouds", _layerConstructor) {
|
||||||
Layers(parent, "clouds", _layerConstructor)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudsDefinition::applyPreset(CloudsPreset preset)
|
void CloudsDefinition::applyPreset(CloudsPreset preset) {
|
||||||
{
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
if (preset == CLOUDS_PRESET_PARTLY_CLOUDY)
|
if (preset == CLOUDS_PRESET_PARTLY_CLOUDY) {
|
||||||
{
|
CloudLayerDefinition *layer = new CloudLayerDefinition(this);
|
||||||
CloudLayerDefinition* layer = new CloudLayerDefinition(this);
|
|
||||||
layer->type = CloudLayerDefinition::STRATOCUMULUS;
|
layer->type = CloudLayerDefinition::STRATOCUMULUS;
|
||||||
layer->setName("Strato-cumulus");
|
layer->setName("Strato-cumulus");
|
||||||
addLayer(layer);
|
addLayer(layer);
|
||||||
|
|
|
@ -8,20 +8,17 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT CloudsDefinition : public Layers
|
class DEFINITIONSHARED_EXPORT CloudsDefinition : public Layers {
|
||||||
{
|
public:
|
||||||
public:
|
CloudsDefinition(DefinitionNode *parent);
|
||||||
CloudsDefinition(DefinitionNode* parent);
|
|
||||||
|
|
||||||
inline CloudLayerDefinition* getCloudLayer(int position) const {return (CloudLayerDefinition*)getLayer(position);}
|
inline CloudLayerDefinition *getCloudLayer(int position) const {
|
||||||
|
return (CloudLayerDefinition *)getLayer(position);
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum
|
typedef enum { CLOUDS_PRESET_PARTLY_CLOUDY } CloudsPreset;
|
||||||
{
|
|
||||||
CLOUDS_PRESET_PARTLY_CLOUDY
|
|
||||||
} CloudsPreset;
|
|
||||||
void applyPreset(CloudsPreset preset);
|
void applyPreset(CloudsPreset preset);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,5 @@
|
||||||
|
|
||||||
#include "DefinitionNode.h"
|
#include "DefinitionNode.h"
|
||||||
|
|
||||||
DefinitionDiff::DefinitionDiff(const DefinitionNode *node):
|
DefinitionDiff::DefinitionDiff(const DefinitionNode *node) : type_name(node->getTypeName()), path(node->getPath()) {
|
||||||
type_name(node->getTypeName()), path(node->getPath())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,21 @@ namespace definition {
|
||||||
*
|
*
|
||||||
* Diffs are used to undo/redo changes.
|
* Diffs are used to undo/redo changes.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT DefinitionDiff
|
class DEFINITIONSHARED_EXPORT DefinitionDiff {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
DefinitionDiff(const DefinitionNode *node);
|
DefinitionDiff(const DefinitionNode *node);
|
||||||
|
|
||||||
inline const std::string &getTypeName() const {return type_name;}
|
inline const std::string &getTypeName() const {
|
||||||
inline const std::string &getPath() const {return path;}
|
return type_name;
|
||||||
|
}
|
||||||
|
inline const std::string &getPath() const {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string type_name;
|
std::string type_name;
|
||||||
std::string path;
|
std::string path;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,171 +8,123 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
DefinitionNode::DefinitionNode(DefinitionNode* parent, const std::string &name, const std::string &type_name):
|
DefinitionNode::DefinitionNode(DefinitionNode *parent, const std::string &name, const std::string &type_name)
|
||||||
parent(parent), type_name(type_name), name(name)
|
: parent(parent), type_name(type_name), name(name) {
|
||||||
{
|
if (parent) {
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
root = parent->root;
|
root = parent->root;
|
||||||
parent->addChild(this);
|
parent->addChild(this);
|
||||||
diffs = NULL;
|
diffs = NULL;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
root = this;
|
root = this;
|
||||||
diffs = new DiffManager(this);
|
diffs = new DiffManager(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinitionNode::~DefinitionNode()
|
DefinitionNode::~DefinitionNode() {
|
||||||
{
|
if (parent) {
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
parent->removeChild(this);
|
parent->removeChild(this);
|
||||||
parent = NULL;
|
parent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diffs)
|
if (diffs) {
|
||||||
{
|
|
||||||
delete diffs;
|
delete diffs;
|
||||||
diffs = NULL;
|
diffs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work on a copy, because the child destructor will modify the array by removing itself using removeChild
|
// Work on a copy, because the child destructor will modify the array by removing itself using removeChild
|
||||||
std::vector<DefinitionNode*> children_copy = children;
|
std::vector<DefinitionNode *> children_copy = children;
|
||||||
for (auto child:children_copy)
|
for (auto child : children_copy) {
|
||||||
{
|
if (child->getParent() == this) {
|
||||||
if (child->getParent() == this)
|
|
||||||
{
|
|
||||||
delete child;
|
delete child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::setName(const std::string &name)
|
void DefinitionNode::setName(const std::string &name) {
|
||||||
{
|
|
||||||
this->name = name;
|
this->name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Scenery* DefinitionNode::getScenery() const
|
const Scenery *DefinitionNode::getScenery() const {
|
||||||
{
|
if (parent) {
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
return parent->getScenery();
|
return parent->getScenery();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DefinitionNode::toString(int indent) const
|
std::string DefinitionNode::toString(int indent) const {
|
||||||
{
|
|
||||||
std::string result;
|
std::string result;
|
||||||
for (int i = 0; i < indent; i++)
|
for (int i = 0; i < indent; i++) {
|
||||||
{
|
|
||||||
result += " ";
|
result += " ";
|
||||||
}
|
}
|
||||||
result += name;
|
result += name;
|
||||||
if (not children.empty())
|
if (not children.empty()) {
|
||||||
{
|
for (auto &child : children) {
|
||||||
for (auto &child: children)
|
|
||||||
{
|
|
||||||
result += "\n" + child->toString(indent + 1);
|
result += "\n" + child->toString(indent + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DefinitionNode::getPath() const
|
std::string DefinitionNode::getPath() const {
|
||||||
{
|
if (parent == root) {
|
||||||
if (parent == root)
|
|
||||||
{
|
|
||||||
return parent->getPath() + name;
|
return parent->getPath() + name;
|
||||||
}
|
} else if (parent) {
|
||||||
else if (parent)
|
|
||||||
{
|
|
||||||
return parent->getPath() + "/" + name;
|
return parent->getPath() + "/" + name;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return "/";
|
return "/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinitionNode *DefinitionNode::findByPath(const std::string &path) const
|
DefinitionNode *DefinitionNode::findByPath(const std::string &path) const {
|
||||||
{
|
if (path.empty()) {
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
} else if (path[0] == '/') {
|
||||||
else if (path[0] == '/')
|
if (path.length() == 1) {
|
||||||
{
|
|
||||||
if (path.length() == 1)
|
|
||||||
{
|
|
||||||
return root;
|
return root;
|
||||||
}
|
} else if (root == this) {
|
||||||
else if (root == this)
|
|
||||||
{
|
|
||||||
return findByPath(path.substr(1));
|
return findByPath(path.substr(1));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return root->findByPath(path);
|
return root->findByPath(path);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
size_t seppos = path.find("/");
|
size_t seppos = path.find("/");
|
||||||
std::string child_name = (seppos == std::string::npos) ? path : path.substr(0, seppos);
|
std::string child_name = (seppos == std::string::npos) ? path : path.substr(0, seppos);
|
||||||
DefinitionNode *child = ((DefinitionNode *)this)->findChildByName(child_name); // FIXME findChildByName should be const
|
DefinitionNode *child =
|
||||||
if (child)
|
((DefinitionNode *)this)->findChildByName(child_name); // FIXME findChildByName should be const
|
||||||
{
|
if (child) {
|
||||||
if (seppos == std::string::npos)
|
if (seppos == std::string::npos) {
|
||||||
{
|
|
||||||
return child;
|
return child;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return child->findByPath(path.substr(seppos + 1));
|
return child->findByPath(path.substr(seppos + 1));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DefinitionNode::applyDiff(const DefinitionDiff *diff, bool)
|
bool DefinitionNode::applyDiff(const DefinitionDiff *diff, bool) {
|
||||||
{
|
|
||||||
// Only do type check, subclasses will do the rest
|
// Only do type check, subclasses will do the rest
|
||||||
if (diff->getTypeName() == type_name)
|
if (diff->getTypeName() == type_name) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
Logs::error() << "Can't apply " << diff->getTypeName() << " diff to " << getName() << " " << type_name
|
||||||
{
|
<< " node" << std::endl;
|
||||||
Logs::error() << "Can't apply " << diff->getTypeName() << " diff to " << getName() << " " << type_name << " node" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::generateInitDiffs(std::vector<const DefinitionDiff *> *) const
|
void DefinitionNode::generateInitDiffs(std::vector<const DefinitionDiff *> *) const {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::addWatcher(DefinitionWatcher *watcher, bool init_diff)
|
void DefinitionNode::addWatcher(DefinitionWatcher *watcher, bool init_diff) {
|
||||||
{
|
if (root && root->diffs) {
|
||||||
if (root && root->diffs)
|
if (init_diff) {
|
||||||
{
|
|
||||||
if (init_diff)
|
|
||||||
{
|
|
||||||
std::vector<const DefinitionDiff *> diffs;
|
std::vector<const DefinitionDiff *> diffs;
|
||||||
generateInitDiffs(&diffs);
|
generateInitDiffs(&diffs);
|
||||||
|
|
||||||
for (auto diff: diffs)
|
for (auto diff : diffs) {
|
||||||
{
|
|
||||||
watcher->nodeChanged(this, diff);
|
watcher->nodeChanged(this, diff);
|
||||||
delete diff;
|
delete diff;
|
||||||
}
|
}
|
||||||
|
@ -181,37 +133,29 @@ void DefinitionNode::addWatcher(DefinitionWatcher *watcher, bool init_diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DefinitionNode::getWatcherCount() const
|
int DefinitionNode::getWatcherCount() const {
|
||||||
{
|
if (root && root->diffs) {
|
||||||
if (root && root->diffs)
|
|
||||||
{
|
|
||||||
return root->diffs->getWatcherCount(this);
|
return root->diffs->getWatcherCount(this);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::save(PackStream* stream) const
|
void DefinitionNode::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int children_count = (int)children.size();
|
int children_count = (int)children.size();
|
||||||
stream->write(&children_count);
|
stream->write(&children_count);
|
||||||
|
|
||||||
for (auto child: children)
|
for (auto child : children) {
|
||||||
{
|
|
||||||
stream->write(child->name);
|
stream->write(child->name);
|
||||||
|
|
||||||
int child_size = child->getStreamSize();
|
int child_size = child->getStreamSize();
|
||||||
if (child_size >= 0)
|
if (child_size >= 0) {
|
||||||
{
|
|
||||||
stream->write(&child_size);
|
stream->write(&child_size);
|
||||||
child->save(stream);
|
child->save(stream);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Child size not known, write it to a temporary stream to know it
|
// Child size not known, write it to a temporary stream to know it
|
||||||
Logs::debug() << "Unknown size for child " << child->name << ", unefficient writing to temporary stream" << std::endl;
|
Logs::debug() << "Unknown size for child " << child->name << ", unefficient writing to temporary stream"
|
||||||
|
<< std::endl;
|
||||||
PackStream substream;
|
PackStream substream;
|
||||||
child->save(&substream);
|
child->save(&substream);
|
||||||
stream->writeFromBuffer(substream, true);
|
stream->writeFromBuffer(substream, true);
|
||||||
|
@ -219,27 +163,22 @@ void DefinitionNode::save(PackStream* stream) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::load(PackStream* stream)
|
void DefinitionNode::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int children_count;
|
int children_count;
|
||||||
|
|
||||||
stream->read(&children_count);
|
stream->read(&children_count);
|
||||||
|
|
||||||
for (int i = 0; i < children_count; i++)
|
for (int i = 0; i < children_count; i++) {
|
||||||
{
|
|
||||||
std::string child_name = stream->readString();
|
std::string child_name = stream->readString();
|
||||||
|
|
||||||
int child_size;
|
int child_size;
|
||||||
stream->read(&child_size);
|
stream->read(&child_size);
|
||||||
|
|
||||||
DefinitionNode *child = findChildByName(child_name);
|
DefinitionNode *child = findChildByName(child_name);
|
||||||
if (child)
|
if (child) {
|
||||||
{
|
|
||||||
// TODO type check
|
// TODO type check
|
||||||
child->load(stream);
|
child->load(stream);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO Ask subclass if it can instanciate a child
|
// TODO Ask subclass if it can instanciate a child
|
||||||
// Else skip length of unknown child
|
// Else skip length of unknown child
|
||||||
stream->skipBytes(child_size);
|
stream->skipBytes(child_size);
|
||||||
|
@ -248,85 +187,65 @@ void DefinitionNode::load(PackStream* stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::copy(DefinitionNode* destination) const
|
void DefinitionNode::copy(DefinitionNode *destination) const {
|
||||||
{
|
if (destination->getTypeName() == getTypeName()) {
|
||||||
if (destination->getTypeName() == getTypeName())
|
|
||||||
{
|
|
||||||
destination->setName(name);
|
destination->setName(name);
|
||||||
for (auto &child: children)
|
for (auto &child : children) {
|
||||||
{
|
|
||||||
DefinitionNode *dest_child = destination->findChildByName(child->name);
|
DefinitionNode *dest_child = destination->findChildByName(child->name);
|
||||||
if (dest_child)
|
if (dest_child) {
|
||||||
{
|
|
||||||
child->copy(dest_child);
|
child->copy(dest_child);
|
||||||
}
|
} else {
|
||||||
else
|
Logs::warning() << "Can't copy to child " << child->name << " of " << destination->getTypeName()
|
||||||
{
|
<< std::endl;
|
||||||
Logs::warning() << "Can't copy to child " << child->name << " of " << destination->getTypeName() << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::validate()
|
void DefinitionNode::validate() {
|
||||||
{
|
for (auto child : children) {
|
||||||
for (auto child: children)
|
|
||||||
{
|
|
||||||
child->validate();
|
child->validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::addChild(DefinitionNode* child)
|
void DefinitionNode::addChild(DefinitionNode *child) {
|
||||||
{
|
if (std::find(children.begin(), children.end(), child) == children.end()) {
|
||||||
if (std::find(children.begin(), children.end(), child) == children.end())
|
|
||||||
{
|
|
||||||
children.push_back(child);
|
children.push_back(child);
|
||||||
child->parent = this;
|
child->parent = this;
|
||||||
child->root = this->root;
|
child->root = this->root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::removeChild(DefinitionNode* child)
|
void DefinitionNode::removeChild(DefinitionNode *child) {
|
||||||
{
|
std::vector<DefinitionNode *>::iterator it = std::find(children.begin(), children.end(), child);
|
||||||
std::vector<DefinitionNode*>::iterator it = std::find(children.begin(), children.end(), child);
|
if (it != children.end()) {
|
||||||
if (it != children.end())
|
|
||||||
{
|
|
||||||
child->parent = NULL;
|
child->parent = NULL;
|
||||||
children.erase(it);
|
children.erase(it);
|
||||||
}
|
} else {
|
||||||
else
|
Logs::warning() << "Trying to remove not found child '" << child->name << "' from '" << name << "'"
|
||||||
{
|
<< std::endl;
|
||||||
Logs::warning() << "Trying to remove not found child '" << child->name << "' from '" << name << "'" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinitionNode *DefinitionNode::findChildByName(const std::string name)
|
DefinitionNode *DefinitionNode::findChildByName(const std::string name) {
|
||||||
{
|
for (auto child : children) {
|
||||||
for (auto child: children)
|
if (child->name == name) {
|
||||||
{
|
|
||||||
if (child->name == name)
|
|
||||||
{
|
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DefinitionNode::getStreamSize() const
|
int DefinitionNode::getStreamSize() const {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefinitionNode::addDiff(const DefinitionDiff *diff)
|
void DefinitionNode::addDiff(const DefinitionDiff *diff) {
|
||||||
{
|
|
||||||
assert(diff->getTypeName() == type_name);
|
assert(diff->getTypeName() == type_name);
|
||||||
|
|
||||||
if (root && root->diffs)
|
if (root && root->diffs) {
|
||||||
{
|
|
||||||
root->diffs->addDiff(this, diff);
|
root->diffs->addDiff(this, diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,29 +9,40 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Base class for all nodes of the definition tree.
|
* Base class for all nodes of the definition tree.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT DefinitionNode
|
class DEFINITIONSHARED_EXPORT DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
DefinitionNode(DefinitionNode *parent, const std::string &name, const std::string &type_name = "");
|
||||||
DefinitionNode(DefinitionNode* parent, const std::string &name, const std::string &type_name = "");
|
|
||||||
virtual ~DefinitionNode();
|
virtual ~DefinitionNode();
|
||||||
|
|
||||||
virtual void save(PackStream* stream) const;
|
virtual void save(PackStream *stream) const;
|
||||||
virtual void load(PackStream* stream);
|
virtual void load(PackStream *stream);
|
||||||
|
|
||||||
virtual void copy(DefinitionNode* destination) const;
|
virtual void copy(DefinitionNode *destination) const;
|
||||||
virtual void validate();
|
virtual void validate();
|
||||||
|
|
||||||
inline const std::string &getName() const {return name;}
|
inline const std::string &getName() const {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
virtual void setName(const std::string &name);
|
virtual void setName(const std::string &name);
|
||||||
|
|
||||||
inline const std::string &getTypeName() const {return type_name;}
|
inline const std::string &getTypeName() const {
|
||||||
|
return type_name;
|
||||||
|
}
|
||||||
|
|
||||||
virtual const Scenery* getScenery() const;
|
virtual const Scenery *getScenery() const;
|
||||||
|
|
||||||
inline const DefinitionNode *getParent() const {return parent;}
|
inline const DefinitionNode *getParent() const {
|
||||||
inline const DefinitionNode *getRoot() const {return root;}
|
return parent;
|
||||||
inline DiffManager *getDiffManager() const {return diffs;}
|
}
|
||||||
inline int getChildrenCount() const {return children.size();}
|
inline const DefinitionNode *getRoot() const {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
inline DiffManager *getDiffManager() const {
|
||||||
|
return diffs;
|
||||||
|
}
|
||||||
|
inline int getChildrenCount() const {
|
||||||
|
return children.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a string representation of the tree (mainly for debugging purposes).
|
* Return a string representation of the tree (mainly for debugging purposes).
|
||||||
|
@ -59,7 +70,7 @@ public:
|
||||||
*
|
*
|
||||||
* Return true if the diff could be applied.
|
* Return true if the diff could be applied.
|
||||||
*/
|
*/
|
||||||
virtual bool applyDiff(const DefinitionDiff *diff, bool backward=false);
|
virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill a diff array to be applied to initialize a proper state for a watcher.
|
* Fill a diff array to be applied to initialize a proper state for a watcher.
|
||||||
|
@ -75,16 +86,16 @@ public:
|
||||||
*
|
*
|
||||||
* If *init_diff* is set to true, a first diff (or several) will be be pushed immediately to initialize the state.
|
* If *init_diff* is set to true, a first diff (or several) will be be pushed immediately to initialize the state.
|
||||||
*/
|
*/
|
||||||
void addWatcher(DefinitionWatcher *watcher, bool init_diff=false);
|
void addWatcher(DefinitionWatcher *watcher, bool init_diff = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current number of watchers.
|
* Get the current number of watchers.
|
||||||
*/
|
*/
|
||||||
int getWatcherCount() const;
|
int getWatcherCount() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addChild(DefinitionNode* child);
|
void addChild(DefinitionNode *child);
|
||||||
void removeChild(DefinitionNode* child);
|
void removeChild(DefinitionNode *child);
|
||||||
virtual DefinitionNode *findChildByName(const std::string name);
|
virtual DefinitionNode *findChildByName(const std::string name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,15 +115,14 @@ protected:
|
||||||
*/
|
*/
|
||||||
void addDiff(const DefinitionDiff *diff);
|
void addDiff(const DefinitionDiff *diff);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DefinitionNode *parent;
|
DefinitionNode *parent;
|
||||||
DefinitionNode *root;
|
DefinitionNode *root;
|
||||||
DiffManager *diffs;
|
DiffManager *diffs;
|
||||||
std::string type_name;
|
std::string type_name;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<DefinitionNode*> children;
|
std::vector<DefinitionNode *> children;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
#include "DefinitionWatcher.h"
|
#include "DefinitionWatcher.h"
|
||||||
|
|
||||||
DefinitionWatcher::DefinitionWatcher()
|
DefinitionWatcher::DefinitionWatcher() {
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,8 @@ namespace definition {
|
||||||
*
|
*
|
||||||
* Watchers will be registered in DiffManager to receive DefinitionDiff objects.
|
* Watchers will be registered in DiffManager to receive DefinitionDiff objects.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT DefinitionWatcher
|
class DEFINITIONSHARED_EXPORT DefinitionWatcher {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
DefinitionWatcher();
|
DefinitionWatcher();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +20,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) = 0;
|
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,38 +4,29 @@
|
||||||
#include "DefinitionDiff.h"
|
#include "DefinitionDiff.h"
|
||||||
#include "DefinitionWatcher.h"
|
#include "DefinitionWatcher.h"
|
||||||
|
|
||||||
DiffManager::DiffManager(DefinitionNode *tree):
|
DiffManager::DiffManager(DefinitionNode *tree) : tree(tree) {
|
||||||
tree(tree)
|
|
||||||
{
|
|
||||||
undone = 0;
|
undone = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiffManager::~DiffManager()
|
DiffManager::~DiffManager() {
|
||||||
{
|
for (auto diff : diffs) {
|
||||||
for (auto diff: diffs)
|
|
||||||
{
|
|
||||||
delete diff;
|
delete diff;
|
||||||
}
|
}
|
||||||
diffs.clear();
|
diffs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffManager::addWatcher(const DefinitionNode *node, DefinitionWatcher *watcher)
|
void DiffManager::addWatcher(const DefinitionNode *node, DefinitionWatcher *watcher) {
|
||||||
{
|
if (std::find(watchers[node].begin(), watchers[node].end(), watcher) == watchers[node].end()) {
|
||||||
if (std::find(watchers[node].begin(), watchers[node].end(), watcher) == watchers[node].end())
|
|
||||||
{
|
|
||||||
watchers[node].push_back(watcher);
|
watchers[node].push_back(watcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DiffManager::getWatcherCount(const DefinitionNode *node)
|
int DiffManager::getWatcherCount(const DefinitionNode *node) {
|
||||||
{
|
|
||||||
return watchers[node].size();
|
return watchers[node].size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff)
|
void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff) {
|
||||||
{
|
while (undone > 0) {
|
||||||
while (undone > 0)
|
|
||||||
{
|
|
||||||
// truncate diffs ahead
|
// truncate diffs ahead
|
||||||
delete diffs.back();
|
delete diffs.back();
|
||||||
diffs.pop_back();
|
diffs.pop_back();
|
||||||
|
@ -47,16 +38,13 @@ void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff)
|
||||||
// TODO Delayed commit (with merge of consecutive diffs)
|
// TODO Delayed commit (with merge of consecutive diffs)
|
||||||
node->applyDiff(diff);
|
node->applyDiff(diff);
|
||||||
|
|
||||||
for (auto watcher: watchers[node])
|
for (auto watcher : watchers[node]) {
|
||||||
{
|
|
||||||
watcher->nodeChanged(node, diff);
|
watcher->nodeChanged(node, diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffManager::undo()
|
void DiffManager::undo() {
|
||||||
{
|
if (undone < (int)diffs.size()) {
|
||||||
if (undone < (int)diffs.size())
|
|
||||||
{
|
|
||||||
undone++;
|
undone++;
|
||||||
const DefinitionDiff *diff = diffs[diffs.size() - undone];
|
const DefinitionDiff *diff = diffs[diffs.size() - undone];
|
||||||
|
|
||||||
|
@ -64,18 +52,15 @@ void DiffManager::undo()
|
||||||
DefinitionNode *node = tree->findByPath(diff->getPath());
|
DefinitionNode *node = tree->findByPath(diff->getPath());
|
||||||
node->applyDiff(diff, true);
|
node->applyDiff(diff, true);
|
||||||
|
|
||||||
for (auto watcher: watchers[node])
|
for (auto watcher : watchers[node]) {
|
||||||
{
|
|
||||||
// FIXME Reverse diff
|
// FIXME Reverse diff
|
||||||
watcher->nodeChanged(node, diff);
|
watcher->nodeChanged(node, diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffManager::redo()
|
void DiffManager::redo() {
|
||||||
{
|
if (undone > 0) {
|
||||||
if (undone > 0)
|
|
||||||
{
|
|
||||||
const DefinitionDiff *diff = diffs[diffs.size() - undone];
|
const DefinitionDiff *diff = diffs[diffs.size() - undone];
|
||||||
undone--;
|
undone--;
|
||||||
|
|
||||||
|
@ -83,10 +68,8 @@ void DiffManager::redo()
|
||||||
DefinitionNode *node = tree->findByPath(diff->getPath());
|
DefinitionNode *node = tree->findByPath(diff->getPath());
|
||||||
node->applyDiff(diff);
|
node->applyDiff(diff);
|
||||||
|
|
||||||
for (auto watcher: watchers[node])
|
for (auto watcher : watchers[node]) {
|
||||||
{
|
|
||||||
watcher->nodeChanged(node, diff);
|
watcher->nodeChanged(node, diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,8 @@ namespace definition {
|
||||||
*
|
*
|
||||||
* Watchers can register themselves to received these diffs.
|
* Watchers can register themselves to received these diffs.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT DiffManager
|
class DEFINITIONSHARED_EXPORT DiffManager {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
DiffManager(DefinitionNode *tree);
|
DiffManager(DefinitionNode *tree);
|
||||||
~DiffManager();
|
~DiffManager();
|
||||||
|
|
||||||
|
@ -47,13 +46,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void redo();
|
void redo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DefinitionNode *tree;
|
DefinitionNode *tree;
|
||||||
int undone;
|
int undone;
|
||||||
std::vector<const DefinitionDiff *> diffs;
|
std::vector<const DefinitionDiff *> diffs;
|
||||||
std::map<const DefinitionNode *, std::vector<DefinitionWatcher *>> watchers;
|
std::map<const DefinitionNode *, std::vector<DefinitionWatcher *>> watchers;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "FloatDiff.h"
|
#include "FloatDiff.h"
|
||||||
|
|
||||||
FloatDiff::FloatDiff(const DefinitionNode *node, double oldvalue, double newvalue):
|
FloatDiff::FloatDiff(const DefinitionNode *node, double oldvalue, double newvalue)
|
||||||
DefinitionDiff(node), oldvalue(oldvalue), newvalue(newvalue)
|
: DefinitionDiff(node), oldvalue(oldvalue), newvalue(newvalue) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,21 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Diff for a FloatNode.
|
* Diff for a FloatNode.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT FloatDiff: public DefinitionDiff
|
class DEFINITIONSHARED_EXPORT FloatDiff : public DefinitionDiff {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
FloatDiff(const DefinitionNode *node, double oldvalue, double newvalue);
|
FloatDiff(const DefinitionNode *node, double oldvalue, double newvalue);
|
||||||
|
|
||||||
inline double getOldValue() const {return oldvalue;}
|
inline double getOldValue() const {
|
||||||
inline double getNewValue() const {return newvalue;}
|
return oldvalue;
|
||||||
|
}
|
||||||
|
inline double getNewValue() const {
|
||||||
|
return newvalue;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double oldvalue;
|
double oldvalue;
|
||||||
double newvalue;
|
double newvalue;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,11 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
FloatNode::FloatNode(DefinitionNode* parent, const std::string &name, double value):
|
FloatNode::FloatNode(DefinitionNode *parent, const std::string &name, double value)
|
||||||
DefinitionNode(parent, name, "float"), value(value)
|
: DefinitionNode(parent, name, "float"), value(value) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FloatNode::toString(int indent) const
|
std::string FloatNode::toString(int indent) const {
|
||||||
{
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
|
||||||
stream << DefinitionNode::toString(indent) << " " << value;
|
stream << DefinitionNode::toString(indent) << " " << value;
|
||||||
|
@ -20,47 +18,36 @@ std::string FloatNode::toString(int indent) const
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatNode::save(PackStream *stream) const
|
void FloatNode::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
stream->write(&value);
|
stream->write(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatNode::load(PackStream *stream)
|
void FloatNode::load(PackStream *stream) {
|
||||||
{
|
|
||||||
stream->read(&value);
|
stream->read(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatNode::copy(DefinitionNode *destination) const
|
void FloatNode::copy(DefinitionNode *destination) const {
|
||||||
{
|
if (destination->getTypeName() == getTypeName()) {
|
||||||
if (destination->getTypeName() == getTypeName())
|
|
||||||
{
|
|
||||||
((FloatNode *)destination)->value = value;
|
((FloatNode *)destination)->value = value;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatNode::setValue(double new_value)
|
void FloatNode::setValue(double new_value) {
|
||||||
{
|
|
||||||
addDiff(produceDiff(new_value));
|
addDiff(produceDiff(new_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
const FloatDiff *FloatNode::produceDiff(double new_value) const
|
const FloatDiff *FloatNode::produceDiff(double new_value) const {
|
||||||
{
|
|
||||||
return new FloatDiff(this, value, new_value);
|
return new FloatDiff(this, value, new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatNode::generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const
|
void FloatNode::generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const {
|
||||||
{
|
|
||||||
diffs->push_back(produceDiff(value));
|
diffs->push_back(produceDiff(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FloatNode::applyDiff(const DefinitionDiff *diff, bool backward)
|
bool FloatNode::applyDiff(const DefinitionDiff *diff, bool backward) {
|
||||||
{
|
if (!DefinitionNode::applyDiff(diff, backward)) {
|
||||||
if (!DefinitionNode::applyDiff(diff, backward))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,19 +57,15 @@ bool FloatNode::applyDiff(const DefinitionDiff *diff, bool backward)
|
||||||
double previous = backward ? float_diff->getNewValue() : float_diff->getOldValue();
|
double previous = backward ? float_diff->getNewValue() : float_diff->getOldValue();
|
||||||
double next = backward ? float_diff->getOldValue() : float_diff->getNewValue();
|
double next = backward ? float_diff->getOldValue() : float_diff->getNewValue();
|
||||||
|
|
||||||
if (value == previous)
|
if (value == previous) {
|
||||||
{
|
|
||||||
value = next;
|
value = next;
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Logs::error() << "Can't apply float diff " << previous << " => " << next << " to " << getName() << std::endl;
|
Logs::error() << "Can't apply float diff " << previous << " => " << next << " to " << getName() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatNode::addValue(double added)
|
void FloatNode::addValue(double added) {
|
||||||
{
|
|
||||||
setValue(value + added);
|
setValue(value + added);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,18 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Node with a single floating point numeric value, for the definition tree.
|
* Node with a single floating point numeric value, for the definition tree.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT FloatNode: public DefinitionNode
|
class DEFINITIONSHARED_EXPORT FloatNode : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
FloatNode(DefinitionNode *parent, const std::string &name, double value = 0.0);
|
||||||
FloatNode(DefinitionNode* parent, const std::string &name, double value = 0.0);
|
|
||||||
|
|
||||||
inline double getValue() const {return value;}
|
inline double getValue() const {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::string toString(int indent) const override;
|
virtual std::string toString(int indent) const override;
|
||||||
virtual void save(PackStream* stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream* stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
virtual void copy(DefinitionNode* destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the float value stored.
|
* Change the float value stored.
|
||||||
|
@ -31,13 +32,13 @@ public:
|
||||||
void setValue(double new_value);
|
void setValue(double new_value);
|
||||||
const FloatDiff *produceDiff(double new_value) const;
|
const FloatDiff *produceDiff(double new_value) const;
|
||||||
void generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const;
|
void generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const;
|
||||||
virtual bool applyDiff(const DefinitionDiff *diff, bool backward=false) override;
|
virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false) override;
|
||||||
|
|
||||||
void addValue(double added);
|
void addValue(double added);
|
||||||
private:
|
|
||||||
|
private:
|
||||||
double value;
|
double value;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,8 @@
|
||||||
|
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
|
|
||||||
GodRaysDefinition::GodRaysDefinition(DefinitionNode *parent):
|
GodRaysDefinition::GodRaysDefinition(DefinitionNode *parent) : DefinitionNode(parent, "godrays", "godrays") {
|
||||||
DefinitionNode(parent, "godrays", "godrays")
|
|
||||||
{
|
|
||||||
penetration = new FloatNode(this, "penetration", 0.01);
|
penetration = new FloatNode(this, "penetration", 0.01);
|
||||||
resistance = new FloatNode(this, "resistance", 0.3);
|
resistance = new FloatNode(this, "resistance", 0.3);
|
||||||
boost = new FloatNode(this, "boost", 8.0);
|
boost = new FloatNode(this, "boost", 8.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,21 +8,25 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT GodRaysDefinition: public DefinitionNode
|
class DEFINITIONSHARED_EXPORT GodRaysDefinition : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
GodRaysDefinition(DefinitionNode *parent);
|
GodRaysDefinition(DefinitionNode *parent);
|
||||||
|
|
||||||
inline FloatNode *propPenetration() const {return penetration;}
|
inline FloatNode *propPenetration() const {
|
||||||
inline FloatNode *propResistance() const {return resistance;}
|
return penetration;
|
||||||
inline FloatNode *propBoost() const {return boost;}
|
}
|
||||||
|
inline FloatNode *propResistance() const {
|
||||||
|
return resistance;
|
||||||
|
}
|
||||||
|
inline FloatNode *propBoost() const {
|
||||||
|
return boost;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FloatNode *penetration;
|
FloatNode *penetration;
|
||||||
FloatNode *resistance;
|
FloatNode *resistance;
|
||||||
FloatNode *boost;
|
FloatNode *boost;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "IntDiff.h"
|
#include "IntDiff.h"
|
||||||
|
|
||||||
IntDiff::IntDiff(const DefinitionNode *node, int oldvalue, int newvalue):
|
IntDiff::IntDiff(const DefinitionNode *node, int oldvalue, int newvalue)
|
||||||
DefinitionDiff(node), oldvalue(oldvalue), newvalue(newvalue)
|
: DefinitionDiff(node), oldvalue(oldvalue), newvalue(newvalue) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,19 +11,21 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Diff for an IntNode.
|
* Diff for an IntNode.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT IntDiff: public DefinitionDiff
|
class DEFINITIONSHARED_EXPORT IntDiff : public DefinitionDiff {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
IntDiff(const DefinitionNode *node, int oldvalue, int newvalue);
|
IntDiff(const DefinitionNode *node, int oldvalue, int newvalue);
|
||||||
|
|
||||||
inline int getOldValue() const {return oldvalue;}
|
inline int getOldValue() const {
|
||||||
inline int getNewValue() const {return newvalue;}
|
return oldvalue;
|
||||||
|
}
|
||||||
|
inline int getNewValue() const {
|
||||||
|
return newvalue;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int oldvalue;
|
int oldvalue;
|
||||||
int newvalue;
|
int newvalue;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,11 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
IntNode::IntNode(DefinitionNode* parent, const std::string &name, int value):
|
IntNode::IntNode(DefinitionNode *parent, const std::string &name, int value)
|
||||||
DefinitionNode(parent, name, "int"), value(value)
|
: DefinitionNode(parent, name, "int"), value(value) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string IntNode::toString(int indent) const
|
std::string IntNode::toString(int indent) const {
|
||||||
{
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
|
||||||
stream << DefinitionNode::toString(indent) << " " << value;
|
stream << DefinitionNode::toString(indent) << " " << value;
|
||||||
|
@ -20,47 +18,36 @@ std::string IntNode::toString(int indent) const
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntNode::save(PackStream *stream) const
|
void IntNode::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
stream->write(&value);
|
stream->write(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntNode::load(PackStream *stream)
|
void IntNode::load(PackStream *stream) {
|
||||||
{
|
|
||||||
stream->read(&value);
|
stream->read(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntNode::copy(DefinitionNode *destination) const
|
void IntNode::copy(DefinitionNode *destination) const {
|
||||||
{
|
if (destination->getTypeName() == getTypeName()) {
|
||||||
if (destination->getTypeName() == getTypeName())
|
|
||||||
{
|
|
||||||
((IntNode *)destination)->value = value;
|
((IntNode *)destination)->value = value;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntNode::setValue(int new_value)
|
void IntNode::setValue(int new_value) {
|
||||||
{
|
|
||||||
addDiff(produceDiff(new_value));
|
addDiff(produceDiff(new_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
const IntDiff *IntNode::produceDiff(int new_value) const
|
const IntDiff *IntNode::produceDiff(int new_value) const {
|
||||||
{
|
|
||||||
return new IntDiff(this, value, new_value);
|
return new IntDiff(this, value, new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntNode::generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const
|
void IntNode::generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const {
|
||||||
{
|
|
||||||
diffs->push_back(produceDiff(value));
|
diffs->push_back(produceDiff(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntNode::applyDiff(const DefinitionDiff *diff, bool backward)
|
bool IntNode::applyDiff(const DefinitionDiff *diff, bool backward) {
|
||||||
{
|
if (!DefinitionNode::applyDiff(diff, backward)) {
|
||||||
if (!DefinitionNode::applyDiff(diff, backward))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,13 +57,10 @@ bool IntNode::applyDiff(const DefinitionDiff *diff, bool backward)
|
||||||
double previous = backward ? int_diff->getNewValue() : int_diff->getOldValue();
|
double previous = backward ? int_diff->getNewValue() : int_diff->getOldValue();
|
||||||
double next = backward ? int_diff->getOldValue() : int_diff->getNewValue();
|
double next = backward ? int_diff->getOldValue() : int_diff->getNewValue();
|
||||||
|
|
||||||
if (value == previous)
|
if (value == previous) {
|
||||||
{
|
|
||||||
value = next;
|
value = next;
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Logs::error() << "Can't apply int diff " << previous << " => " << next << " to " << getName() << std::endl;
|
Logs::error() << "Can't apply int diff " << previous << " => " << next << " to " << getName() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,18 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Node with a single integer value, for the definition tree.
|
* Node with a single integer value, for the definition tree.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT IntNode: public DefinitionNode
|
class DEFINITIONSHARED_EXPORT IntNode : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
IntNode(DefinitionNode *parent, const std::string &name, int value = 0);
|
||||||
IntNode(DefinitionNode* parent, const std::string &name, int value = 0);
|
|
||||||
|
|
||||||
inline int getValue() const {return value;}
|
inline int getValue() const {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::string toString(int indent) const override;
|
virtual std::string toString(int indent) const override;
|
||||||
virtual void save(PackStream* stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream* stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
virtual void copy(DefinitionNode* destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the int value stored.
|
* Change the int value stored.
|
||||||
|
@ -31,12 +32,11 @@ public:
|
||||||
void setValue(int new_value);
|
void setValue(int new_value);
|
||||||
const IntDiff *produceDiff(int new_value) const;
|
const IntDiff *produceDiff(int new_value) const;
|
||||||
void generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const;
|
void generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const;
|
||||||
virtual bool applyDiff(const DefinitionDiff *diff, bool backward=false) override;
|
virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,57 +3,48 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
|
|
||||||
Layers::Layers(DefinitionNode* parent, const std::string &name, LayerConstructor layer_constructor):
|
Layers::Layers(DefinitionNode *parent, const std::string &name, LayerConstructor layer_constructor)
|
||||||
DefinitionNode(parent, name, "layers" + name), layer_constructor(layer_constructor)
|
: DefinitionNode(parent, name, "layers" + name), layer_constructor(layer_constructor) {
|
||||||
{
|
|
||||||
max_layer_count = 100;
|
max_layer_count = 100;
|
||||||
null_layer = layer_constructor(this);
|
null_layer = layer_constructor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Layers::~Layers()
|
Layers::~Layers() {
|
||||||
{
|
|
||||||
clear();
|
clear();
|
||||||
delete null_layer;
|
delete null_layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::save(PackStream *stream) const
|
void Layers::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int layer_count = (int)layers.size();
|
int layer_count = (int)layers.size();
|
||||||
stream->write(&layer_count);
|
stream->write(&layer_count);
|
||||||
|
|
||||||
for (int i = 0; i < layer_count; i++)
|
for (int i = 0; i < layer_count; i++) {
|
||||||
{
|
|
||||||
stream->write(layers[i]->getName());
|
stream->write(layers[i]->getName());
|
||||||
layers[i]->save(stream);
|
layers[i]->save(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::load(PackStream *stream)
|
void Layers::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int layer_count;
|
int layer_count;
|
||||||
stream->read(&layer_count);
|
stream->read(&layer_count);
|
||||||
|
|
||||||
if (layer_count > max_layer_count)
|
if (layer_count > max_layer_count) {
|
||||||
{
|
|
||||||
layer_count = max_layer_count;
|
layer_count = max_layer_count;
|
||||||
}
|
}
|
||||||
clear();
|
clear();
|
||||||
for (int i = 0; i < layer_count; i++)
|
for (int i = 0; i < layer_count; i++) {
|
||||||
{
|
|
||||||
int position = addLayer();
|
int position = addLayer();
|
||||||
if (position >= 0)
|
if (position >= 0) {
|
||||||
{
|
|
||||||
layers[position]->setName(stream->readString());
|
layers[position]->setName(stream->readString());
|
||||||
layers[position]->load(stream);
|
layers[position]->load(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::copy(DefinitionNode* destination_) const
|
void Layers::copy(DefinitionNode *destination_) const {
|
||||||
{
|
|
||||||
DefinitionNode::copy(destination_);
|
DefinitionNode::copy(destination_);
|
||||||
|
|
||||||
Layers* destination = (Layers*)destination_;
|
Layers *destination = (Layers *)destination_;
|
||||||
|
|
||||||
destination->clear();
|
destination->clear();
|
||||||
|
|
||||||
|
@ -61,142 +52,113 @@ void Layers::copy(DefinitionNode* destination_) const
|
||||||
|
|
||||||
null_layer->copy(destination->null_layer);
|
null_layer->copy(destination->null_layer);
|
||||||
|
|
||||||
for (auto layer: layers)
|
for (auto layer : layers) {
|
||||||
{
|
|
||||||
int position = destination->addLayer();
|
int position = destination->addLayer();
|
||||||
DefinitionNode* new_layer = destination->getLayer(position);
|
DefinitionNode *new_layer = destination->getLayer(position);
|
||||||
layer->copy(new_layer);
|
layer->copy(new_layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Layers* Layers::newCopy() const
|
Layers *Layers::newCopy() const {
|
||||||
{
|
Layers *result = new Layers(NULL, getName(), layer_constructor);
|
||||||
Layers* result = new Layers(NULL, getName(), layer_constructor);
|
|
||||||
copy(result);
|
copy(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::setMaxLayerCount(int max_layer_count)
|
void Layers::setMaxLayerCount(int max_layer_count) {
|
||||||
{
|
|
||||||
this->max_layer_count = max_layer_count;
|
this->max_layer_count = max_layer_count;
|
||||||
// TODO Delete overlimit layers ?
|
// TODO Delete overlimit layers ?
|
||||||
}
|
}
|
||||||
|
|
||||||
int Layers::count() const
|
int Layers::count() const {
|
||||||
{
|
|
||||||
return layers.size();
|
return layers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinitionNode* Layers::getLayer(int position) const
|
DefinitionNode *Layers::getLayer(int position) const {
|
||||||
{
|
if (position >= 0 and position < (int)layers.size()) {
|
||||||
if (position >= 0 and position < (int)layers.size())
|
|
||||||
{
|
|
||||||
return layers[position];
|
return layers[position];
|
||||||
}
|
} else {
|
||||||
else
|
Logs::warning() << "Asked for a undefined layer " << position << " on a total of " << (int)layers.size()
|
||||||
{
|
<< std::endl;
|
||||||
Logs::warning() << "Asked for a undefined layer " << position << " on a total of " << (int)layers.size() << std::endl;
|
|
||||||
return null_layer;
|
return null_layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Layers::findLayer(DefinitionNode* layer) const
|
int Layers::findLayer(DefinitionNode *layer) const {
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto it:layers)
|
for (auto it : layers) {
|
||||||
{
|
if (it == layer) {
|
||||||
if (it == layer)
|
|
||||||
{
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
Logs::warning() << "Layer " << layer << " (" << layer->getName() << " not found, on a total of " << (int)layers.size() << std::endl;
|
Logs::warning() << "Layer " << layer << " (" << layer->getName() << " not found, on a total of "
|
||||||
|
<< (int)layers.size() << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Layers::addLayer(DefinitionNode* layer)
|
int Layers::addLayer(DefinitionNode *layer) {
|
||||||
{
|
if ((int)layers.size() < max_layer_count) {
|
||||||
if ((int)layers.size() < max_layer_count)
|
|
||||||
{
|
|
||||||
layers.push_back(layer);
|
layers.push_back(layer);
|
||||||
addChild(layer);
|
addChild(layer);
|
||||||
return layers.size() - 1;
|
return layers.size() - 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Logs::warning() << "Add layer ignored because limit of " << max_layer_count << " reached" << std::endl;
|
Logs::warning() << "Add layer ignored because limit of " << max_layer_count << " reached" << std::endl;
|
||||||
delete layer;
|
delete layer;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Layers::addLayer()
|
int Layers::addLayer() {
|
||||||
{
|
|
||||||
return addLayer(layer_constructor(this));
|
return addLayer(layer_constructor(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::removeLayer(int position)
|
void Layers::removeLayer(int position) {
|
||||||
{
|
if (position >= 0 and position < (int)layers.size()) {
|
||||||
if (position >= 0 and position < (int)layers.size())
|
DefinitionNode *removed = layers[position];
|
||||||
{
|
|
||||||
DefinitionNode* removed = layers[position];
|
|
||||||
removeChild(removed);
|
removeChild(removed);
|
||||||
layers.erase(layers.begin() + position);
|
layers.erase(layers.begin() + position);
|
||||||
delete removed;
|
delete removed;
|
||||||
}
|
} else {
|
||||||
else
|
Logs::warning() << "Removing unknown layer " << position << " on " << (int)layers.size() << " from '"
|
||||||
{
|
<< getName() << "'" << std::endl;
|
||||||
Logs::warning() << "Removing unknown layer " << position << " on " << (int)layers.size() << " from '" << getName() << "'" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::removeLayer(DefinitionNode* layer)
|
void Layers::removeLayer(DefinitionNode *layer) {
|
||||||
{
|
|
||||||
removeLayer(findLayer(layer));
|
removeLayer(findLayer(layer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::moveLayer(int old_position, int new_position)
|
void Layers::moveLayer(int old_position, int new_position) {
|
||||||
{
|
if (old_position >= 0 and old_position < (int)layers.size() and new_position >= 0 and
|
||||||
if (old_position >= 0 and old_position < (int)layers.size() and new_position >= 0 and new_position < (int)layers.size())
|
new_position < (int)layers.size()) {
|
||||||
{
|
DefinitionNode *layer = layers[old_position];
|
||||||
DefinitionNode* layer = layers[old_position];
|
|
||||||
layers.erase(layers.begin() + old_position);
|
layers.erase(layers.begin() + old_position);
|
||||||
layers.insert(layers.begin() + new_position, layer);
|
layers.insert(layers.begin() + new_position, layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::moveLayer(DefinitionNode* layer, int new_position)
|
void Layers::moveLayer(DefinitionNode *layer, int new_position) {
|
||||||
{
|
|
||||||
moveLayer(findLayer(layer), new_position);
|
moveLayer(findLayer(layer), new_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::clear()
|
void Layers::clear() {
|
||||||
{
|
while (layers.size() > 0) {
|
||||||
while (layers.size() > 0)
|
|
||||||
{
|
|
||||||
removeLayer(0);
|
removeLayer(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinitionNode *Layers::findChildByName(const std::string name)
|
DefinitionNode *Layers::findChildByName(const std::string name) {
|
||||||
{
|
|
||||||
DefinitionNode *result = DefinitionNode::findChildByName(name);
|
DefinitionNode *result = DefinitionNode::findChildByName(name);
|
||||||
if (result)
|
if (result) {
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
int position = addLayer();
|
int position = addLayer();
|
||||||
if (position >= 0)
|
if (position >= 0) {
|
||||||
{
|
|
||||||
result = getLayer(position);
|
result = getLayer(position);
|
||||||
result->setName(name);
|
result->setName(name);
|
||||||
return result;
|
return result;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,27 +8,26 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
typedef DefinitionNode* (*LayerConstructor)(Layers* parent);
|
typedef DefinitionNode *(*LayerConstructor)(Layers *parent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Layers of definitions, ideally all of the same type.
|
* @brief Layers of definitions, ideally all of the same type.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT Layers:public DefinitionNode
|
class DEFINITIONSHARED_EXPORT Layers : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
Layers(DefinitionNode *parent, const std::string &name, LayerConstructor layer_constructor);
|
||||||
Layers(DefinitionNode* parent, const std::string &name, LayerConstructor layer_constructor);
|
|
||||||
virtual ~Layers();
|
virtual ~Layers();
|
||||||
|
|
||||||
virtual void save(PackStream *stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream *stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
virtual void copy(DefinitionNode* destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
Layers* newCopy() const;
|
Layers *newCopy() const;
|
||||||
|
|
||||||
void setMaxLayerCount(int max_layer_count);
|
void setMaxLayerCount(int max_layer_count);
|
||||||
|
|
||||||
int count() const;
|
int count() const;
|
||||||
DefinitionNode* getLayer(int position) const;
|
DefinitionNode *getLayer(int position) const;
|
||||||
int findLayer(DefinitionNode* layer) const;
|
int findLayer(DefinitionNode *layer) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add a new layer
|
* @brief Add a new layer
|
||||||
|
@ -40,22 +39,20 @@ public:
|
||||||
int addLayer(DefinitionNode *layer);
|
int addLayer(DefinitionNode *layer);
|
||||||
int addLayer();
|
int addLayer();
|
||||||
void removeLayer(int position);
|
void removeLayer(int position);
|
||||||
void removeLayer(DefinitionNode* layer);
|
void removeLayer(DefinitionNode *layer);
|
||||||
void moveLayer(int old_position, int new_position);
|
void moveLayer(int old_position, int new_position);
|
||||||
void moveLayer(DefinitionNode* layer, int new_position);
|
void moveLayer(DefinitionNode *layer, int new_position);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual DefinitionNode *findChildByName(const std::string name) override;
|
virtual DefinitionNode *findChildByName(const std::string name) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LayerConstructor layer_constructor;
|
LayerConstructor layer_constructor;
|
||||||
int max_layer_count;
|
int max_layer_count;
|
||||||
std::vector<DefinitionNode*> layers;
|
std::vector<DefinitionNode *> layers;
|
||||||
DefinitionNode* null_layer;
|
DefinitionNode *null_layer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,15 @@
|
||||||
#include "NoiseGenerator.h"
|
#include "NoiseGenerator.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
|
|
||||||
NoiseNode::NoiseNode(DefinitionNode *parent):
|
NoiseNode::NoiseNode(DefinitionNode *parent) : DefinitionNode(parent, "noise") {
|
||||||
DefinitionNode(parent, "noise")
|
|
||||||
{
|
|
||||||
noise = new NoiseGenerator();
|
noise = new NoiseGenerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
NoiseNode::~NoiseNode()
|
NoiseNode::~NoiseNode() {
|
||||||
{
|
|
||||||
delete noise;
|
delete noise;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseNode::setLevels(int levels, double min_value, double max_value)
|
void NoiseNode::setLevels(int levels, double min_value, double max_value) {
|
||||||
{
|
|
||||||
noise->clearLevels();
|
noise->clearLevels();
|
||||||
noise->addLevelsSimple(levels, 1.0, -1.0, 1.0, 0.5);
|
noise->addLevelsSimple(levels, 1.0, -1.0, 1.0, 0.5);
|
||||||
noise->normalizeAmplitude(min_value, max_value, false);
|
noise->normalizeAmplitude(min_value, max_value, false);
|
||||||
|
@ -23,29 +19,22 @@ void NoiseNode::setLevels(int levels, double min_value, double max_value)
|
||||||
noise->validate();
|
noise->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseNode::save(PackStream *stream) const
|
void NoiseNode::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
noise->save(stream);
|
noise->save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseNode::load(PackStream *stream)
|
void NoiseNode::load(PackStream *stream) {
|
||||||
{
|
|
||||||
noise->load(stream);
|
noise->load(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseNode::copy(DefinitionNode *destination) const
|
void NoiseNode::copy(DefinitionNode *destination) const {
|
||||||
{
|
if (destination->getTypeName() == getTypeName()) {
|
||||||
if (destination->getTypeName() == getTypeName())
|
|
||||||
{
|
|
||||||
noise->copy(((NoiseNode *)destination)->noise);
|
noise->copy(((NoiseNode *)destination)->noise);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoiseNode::validate()
|
void NoiseNode::validate() {
|
||||||
{
|
|
||||||
noise->validate();
|
noise->validate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,30 +11,29 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Definition node with noise parameters.
|
* Definition node with noise parameters.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT NoiseNode: public DefinitionNode
|
class DEFINITIONSHARED_EXPORT NoiseNode : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
NoiseNode(DefinitionNode *parent);
|
NoiseNode(DefinitionNode *parent);
|
||||||
virtual ~NoiseNode();
|
virtual ~NoiseNode();
|
||||||
|
|
||||||
inline const NoiseGenerator *getGenerator() {return noise;}
|
inline const NoiseGenerator *getGenerator() {
|
||||||
|
return noise;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the number of levels to use in the noise generator.
|
* Set the number of levels to use in the noise generator.
|
||||||
*/
|
*/
|
||||||
void setLevels(int levels, double min_value=-1.0, double max_value=1.0);
|
void setLevels(int levels, double min_value = -1.0, double max_value = 1.0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void save(PackStream *stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream *stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
virtual void copy(DefinitionNode *destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
virtual void validate() override;
|
virtual void validate() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NoiseGenerator *noise;
|
NoiseGenerator *noise;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,40 +6,33 @@
|
||||||
#include "PaintedGridData.h"
|
#include "PaintedGridData.h"
|
||||||
#include "PaintedGridBrush.h"
|
#include "PaintedGridBrush.h"
|
||||||
|
|
||||||
PaintedGrid::PaintedGrid(DefinitionNode *parent):
|
PaintedGrid::PaintedGrid(DefinitionNode *parent) : DefinitionNode(parent, "grid", "grid") {
|
||||||
DefinitionNode(parent, "grid", "grid")
|
|
||||||
{
|
|
||||||
merged_data = new PaintedGridData;
|
merged_data = new PaintedGridData;
|
||||||
brush_data = new PaintedGridData;
|
brush_data = new PaintedGridData;
|
||||||
}
|
}
|
||||||
|
|
||||||
PaintedGrid::~PaintedGrid()
|
PaintedGrid::~PaintedGrid() {
|
||||||
{
|
|
||||||
delete merged_data;
|
delete merged_data;
|
||||||
delete brush_data;
|
delete brush_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGrid::copy(DefinitionNode *_destination) const
|
void PaintedGrid::copy(DefinitionNode *_destination) const {
|
||||||
{
|
PaintedGrid *destination = (PaintedGrid *)_destination;
|
||||||
PaintedGrid* destination = (PaintedGrid *)_destination;
|
|
||||||
|
|
||||||
merged_data->copy(destination->merged_data);
|
merged_data->copy(destination->merged_data);
|
||||||
destination->brush_data->clear();
|
destination->brush_data->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGrid::save(PackStream *stream) const
|
void PaintedGrid::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
merged_data->save(stream);
|
merged_data->save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGrid::load(PackStream *stream)
|
void PaintedGrid::load(PackStream *stream) {
|
||||||
{
|
|
||||||
merged_data->load(stream);
|
merged_data->load(stream);
|
||||||
brush_data->clear();
|
brush_data->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PaintedGrid::getInterpolatedValue(double x, double y, double *result) const
|
bool PaintedGrid::getInterpolatedValue(double x, double y, double *result) const {
|
||||||
{
|
|
||||||
int ix, iy;
|
int ix, iy;
|
||||||
int xlow;
|
int xlow;
|
||||||
int ylow;
|
int ylow;
|
||||||
|
@ -48,27 +41,20 @@ bool PaintedGrid::getInterpolatedValue(double x, double y, double *result) const
|
||||||
ylow = floor(y);
|
ylow = floor(y);
|
||||||
|
|
||||||
int hit = 0;
|
int hit = 0;
|
||||||
for (ix = xlow - 1; ix <= xlow + 2 && !hit; ix++)
|
for (ix = xlow - 1; ix <= xlow + 2 && !hit; ix++) {
|
||||||
{
|
for (iy = ylow - 1; iy <= ylow + 2 && !hit; iy++) {
|
||||||
for (iy = ylow - 1; iy <= ylow + 2 && !hit; iy++)
|
if (getDataPointer(brush_data, x, y, NULL, false) || getDataPointer(merged_data, x, y, NULL, false)) {
|
||||||
{
|
|
||||||
if (getDataPointer(brush_data, x, y, NULL, false) || getDataPointer(merged_data, x, y, NULL, false))
|
|
||||||
{
|
|
||||||
hit = 1;
|
hit = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit && result)
|
if (hit && result) {
|
||||||
{
|
|
||||||
double stencil[16];
|
double stencil[16];
|
||||||
double value;
|
double value;
|
||||||
for (ix = xlow - 1; ix <= xlow + 2; ix++)
|
for (ix = xlow - 1; ix <= xlow + 2; ix++) {
|
||||||
{
|
for (iy = ylow - 1; iy <= ylow + 2; iy++) {
|
||||||
for (iy = ylow - 1; iy <= ylow + 2; iy++)
|
if (!getGridValue(ix, iy, &value)) {
|
||||||
{
|
|
||||||
if (!getGridValue(ix, iy, &value))
|
|
||||||
{
|
|
||||||
value = getInitialValue(ix, iy);
|
value = getInitialValue(ix, iy);
|
||||||
}
|
}
|
||||||
stencil[(iy - (ylow - 1)) * 4 + ix - (xlow - 1)] = value;
|
stencil[(iy - (ylow - 1)) * 4 + ix - (xlow - 1)] = value;
|
||||||
|
@ -81,67 +67,51 @@ bool PaintedGrid::getInterpolatedValue(double x, double y, double *result) const
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PaintedGrid::getGridValue(int x, int y, double *result) const
|
bool PaintedGrid::getGridValue(int x, int y, double *result) const {
|
||||||
{
|
double *dpointer;
|
||||||
double* dpointer;
|
|
||||||
dpointer = getDataPointer(brush_data, x, y, NULL, false);
|
dpointer = getDataPointer(brush_data, x, y, NULL, false);
|
||||||
if (dpointer)
|
if (dpointer) {
|
||||||
{
|
|
||||||
*result = *dpointer;
|
*result = *dpointer;
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
dpointer = getDataPointer(merged_data, x, y, NULL, false);
|
dpointer = getDataPointer(merged_data, x, y, NULL, false);
|
||||||
if (dpointer)
|
if (dpointer) {
|
||||||
{
|
|
||||||
*result = *dpointer;
|
*result = *dpointer;
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGrid::getFinalValue(double x, double y) const
|
double PaintedGrid::getFinalValue(double x, double y) const {
|
||||||
{
|
|
||||||
double result;
|
double result;
|
||||||
|
|
||||||
if (getInterpolatedValue(x, y, &result))
|
if (getInterpolatedValue(x, y, &result)) {
|
||||||
{
|
|
||||||
return result;
|
return result;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return getInitialValue(x, y);
|
return getInitialValue(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PaintedGrid::hasPainting() const
|
bool PaintedGrid::hasPainting() const {
|
||||||
{
|
|
||||||
return merged_data->hasData() || brush_data->hasData();
|
return merged_data->hasData() || brush_data->hasData();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PaintedGrid::isPainted(int x, int y) const
|
bool PaintedGrid::isPainted(int x, int y) const {
|
||||||
{
|
|
||||||
return getDataPointer(brush_data, x, y, NULL, false) || getDataPointer(merged_data, x, y, NULL, false);
|
return getDataPointer(brush_data, x, y, NULL, false) || getDataPointer(merged_data, x, y, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long PaintedGrid::getMemoryStats() const
|
unsigned long PaintedGrid::getMemoryStats() const {
|
||||||
{
|
|
||||||
return merged_data->memsize + brush_data->memsize;
|
return merged_data->memsize + brush_data->memsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGrid::clearPainting()
|
void PaintedGrid::clearPainting() {
|
||||||
{
|
|
||||||
merged_data->clear();
|
merged_data->clear();
|
||||||
brush_data->clear();
|
brush_data->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGrid::applyBrush(const PaintedGridBrush &brush, double x, double y, double force, bool commit)
|
void PaintedGrid::applyBrush(const PaintedGridBrush &brush, double x, double y, double force, bool commit) {
|
||||||
{
|
|
||||||
int xstart, xend, ystart, yend;
|
int xstart, xend, ystart, yend;
|
||||||
|
|
||||||
brush.getArea(x, y, &xstart, &ystart, &xend, ¥d);
|
brush.getArea(x, y, &xstart, &ystart, &xend, ¥d);
|
||||||
|
@ -149,41 +119,34 @@ void PaintedGrid::applyBrush(const PaintedGridBrush &brush, double x, double y,
|
||||||
int ix, iy;
|
int ix, iy;
|
||||||
double dx, dy, influence;
|
double dx, dy, influence;
|
||||||
|
|
||||||
for (ix = xstart; ix <= xend; ix++)
|
for (ix = xstart; ix <= xend; ix++) {
|
||||||
{
|
|
||||||
dx = (double)ix;
|
dx = (double)ix;
|
||||||
for (iy = ystart; iy <= yend; iy++)
|
for (iy = ystart; iy <= yend; iy++) {
|
||||||
{
|
|
||||||
dy = (double)iy;
|
dy = (double)iy;
|
||||||
|
|
||||||
influence = brush.getInfluence(x - dx, y - dy);
|
influence = brush.getInfluence(x - dx, y - dy);
|
||||||
|
|
||||||
if (influence > 0.0)
|
if (influence > 0.0) {
|
||||||
{
|
double *dpointer = getDataPointer(brush_data, ix, iy, merged_data, true);
|
||||||
double* dpointer = getDataPointer(brush_data, ix, iy, merged_data, true);
|
|
||||||
*dpointer = brush.getValue(this, dx, dy, *dpointer, influence, force);
|
*dpointer = brush.getValue(this, dx, dy, *dpointer, influence, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commit)
|
if (commit) {
|
||||||
{
|
|
||||||
endBrushStroke();
|
endBrushStroke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGrid::endBrushStroke()
|
void PaintedGrid::endBrushStroke() {
|
||||||
{
|
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
PaintedGridData* data = brush_data;
|
PaintedGridData *data = brush_data;
|
||||||
|
|
||||||
for (i = 0; i < data->rows_count; i++)
|
for (i = 0; i < data->rows_count; i++) {
|
||||||
{
|
for (j = 0; j < data->rows[i].pixel_groups_count; j++) {
|
||||||
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
|
for (k = 0; k < data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart + 1; k++) {
|
||||||
{
|
double *dpointer =
|
||||||
for (k = 0; k < data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart + 1; k++)
|
getDataPointer(merged_data, data->rows[i].pixel_groups[j].xstart + k, data->rows[i].y, NULL, true);
|
||||||
{
|
|
||||||
double* dpointer = getDataPointer(merged_data, data->rows[i].pixel_groups[j].xstart + k, data->rows[i].y, NULL, true);
|
|
||||||
*dpointer = data->rows[i].pixel_groups[j].height[k];
|
*dpointer = data->rows[i].pixel_groups[j].height[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,63 +155,51 @@ void PaintedGrid::endBrushStroke()
|
||||||
brush_data->clear();
|
brush_data->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGrid::getInitialValue(double, double) const
|
double PaintedGrid::getInitialValue(double, double) const {
|
||||||
{
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double *PaintedGrid::getDataPointer(PaintedGridData *data, int x, int y, PaintedGridData *fallback, bool grow) const
|
double *PaintedGrid::getDataPointer(PaintedGridData *data, int x, int y, PaintedGridData *fallback, bool grow) const {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Find row */
|
/* Find row */
|
||||||
/* TODO Dichotomic search */
|
/* TODO Dichotomic search */
|
||||||
PaintedGridData::HeightMapRow* row;
|
PaintedGridData::HeightMapRow *row;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < data->rows_count && data->rows[i].y < y)
|
while (i < data->rows_count && data->rows[i].y < y) {
|
||||||
{
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i < data->rows_count && data->rows[i].y == y)
|
if (i < data->rows_count && data->rows[i].y == y) {
|
||||||
{
|
|
||||||
row = data->rows + i;
|
row = data->rows + i;
|
||||||
}
|
} else if (grow) {
|
||||||
else if (grow)
|
row = (PaintedGridData::HeightMapRow *)Memory::naiveArrayInsert(
|
||||||
{
|
(void **)&data->rows, sizeof(PaintedGridData::HeightMapRow), data->rows_count, i);
|
||||||
row = (PaintedGridData::HeightMapRow*)Memory::naiveArrayInsert((void**)&data->rows, sizeof(PaintedGridData::HeightMapRow), data->rows_count, i);
|
|
||||||
|
|
||||||
row->y = y;
|
row->y = y;
|
||||||
row->pixel_groups_count = 0;
|
row->pixel_groups_count = 0;
|
||||||
row->pixel_groups = (PaintedGridData::HeightMapPixelGroup*)malloc(1);
|
row->pixel_groups = (PaintedGridData::HeightMapPixelGroup *)malloc(1);
|
||||||
|
|
||||||
data->rows_count++;
|
data->rows_count++;
|
||||||
data->memsize += sizeof(PaintedGridData::HeightMapRow);
|
data->memsize += sizeof(PaintedGridData::HeightMapRow);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/* Check rows */
|
/* Check rows */
|
||||||
for (i = 1; i < data->rows_count; i++)
|
for (i = 1; i < data->rows_count; i++) {
|
||||||
{
|
|
||||||
assert(data->rows[i].y > data->rows[i - 1].y);
|
assert(data->rows[i].y > data->rows[i - 1].y);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find pixel group */
|
/* Find pixel group */
|
||||||
PaintedGridData::HeightMapPixelGroup* pixel_group = NULL;
|
PaintedGridData::HeightMapPixelGroup *pixel_group = NULL;
|
||||||
for (i = 0; i < row->pixel_groups_count; i++)
|
for (i = 0; i < row->pixel_groups_count; i++) {
|
||||||
{
|
if (x < row->pixel_groups[i].xstart - 1) {
|
||||||
if (x < row->pixel_groups[i].xstart - 1)
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else if (x <= row->pixel_groups[i].xend + 1) {
|
||||||
else if (x <= row->pixel_groups[i].xend + 1)
|
if (x == row->pixel_groups[i].xend + 1 && i < row->pixel_groups_count - 1 &&
|
||||||
{
|
x == row->pixel_groups[i + 1].xstart) {
|
||||||
if (x == row->pixel_groups[i].xend + 1 && i < row->pixel_groups_count - 1 && x == row->pixel_groups[i + 1].xstart)
|
|
||||||
{
|
|
||||||
/* Choose next group if it already includes the pixel */
|
/* Choose next group if it already includes the pixel */
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -258,53 +209,47 @@ double *PaintedGrid::getDataPointer(PaintedGridData *data, int x, int y, Painted
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Alter pixel group */
|
/* Alter pixel group */
|
||||||
double* pixel;
|
double *pixel;
|
||||||
int added = 1;
|
int added = 1;
|
||||||
if (!pixel_group)
|
if (!pixel_group) {
|
||||||
{
|
if (!grow) {
|
||||||
if (!grow)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the pixel group with one pixel */
|
/* Create the pixel group with one pixel */
|
||||||
pixel_group = (PaintedGridData::HeightMapPixelGroup*)Memory::naiveArrayInsert((void**)&row->pixel_groups, sizeof(PaintedGridData::HeightMapPixelGroup), row->pixel_groups_count, i);
|
pixel_group = (PaintedGridData::HeightMapPixelGroup *)Memory::naiveArrayInsert(
|
||||||
|
(void **)&row->pixel_groups, sizeof(PaintedGridData::HeightMapPixelGroup), row->pixel_groups_count, i);
|
||||||
|
|
||||||
pixel_group->xstart = x;
|
pixel_group->xstart = x;
|
||||||
pixel_group->xend = x;
|
pixel_group->xend = x;
|
||||||
pixel_group->height = (double*)malloc(sizeof(double));
|
pixel_group->height = (double *)malloc(sizeof(double));
|
||||||
|
|
||||||
pixel = pixel_group->height;
|
pixel = pixel_group->height;
|
||||||
|
|
||||||
row->pixel_groups_count++;
|
row->pixel_groups_count++;
|
||||||
data->memsize += sizeof(PaintedGridData::HeightMapPixelGroup) + sizeof(double);
|
data->memsize += sizeof(PaintedGridData::HeightMapPixelGroup) + sizeof(double);
|
||||||
}
|
} else if (x == pixel_group->xstart - 1) {
|
||||||
else if (x == pixel_group->xstart - 1)
|
if (!grow) {
|
||||||
{
|
|
||||||
if (!grow)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extend the rowgroup at start */
|
/* Extend the rowgroup at start */
|
||||||
pixel_group->xstart--;
|
pixel_group->xstart--;
|
||||||
pixel = (double*)Memory::naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, 0);
|
pixel = (double *)Memory::naiveArrayInsert((void **)&pixel_group->height, sizeof(double),
|
||||||
|
pixel_group->xend - pixel_group->xstart, 0);
|
||||||
data->memsize += sizeof(double);
|
data->memsize += sizeof(double);
|
||||||
}
|
} else if (x == pixel_group->xend + 1) {
|
||||||
else if (x == pixel_group->xend + 1)
|
if (!grow) {
|
||||||
{
|
|
||||||
if (!grow)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extend the rowgroup at end */
|
/* Extend the rowgroup at end */
|
||||||
pixel_group->xend++;
|
pixel_group->xend++;
|
||||||
pixel = (double*)Memory::naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, pixel_group->xend - pixel_group->xstart);
|
pixel = (double *)Memory::naiveArrayInsert((void **)&pixel_group->height, sizeof(double),
|
||||||
|
pixel_group->xend - pixel_group->xstart,
|
||||||
|
pixel_group->xend - pixel_group->xstart);
|
||||||
data->memsize += sizeof(double);
|
data->memsize += sizeof(double);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(x >= pixel_group->xstart);
|
assert(x >= pixel_group->xstart);
|
||||||
assert(x <= pixel_group->xend);
|
assert(x <= pixel_group->xend);
|
||||||
pixel = pixel_group->height + x - pixel_group->xstart;
|
pixel = pixel_group->height + x - pixel_group->xstart;
|
||||||
|
@ -313,14 +258,11 @@ double *PaintedGrid::getDataPointer(PaintedGridData *data, int x, int y, Painted
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/* Check pixel groups */
|
/* Check pixel groups */
|
||||||
for (i = 0; i < row->pixel_groups_count; i++)
|
for (i = 0; i < row->pixel_groups_count; i++) {
|
||||||
{
|
if (i > 0) {
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
assert(row->pixel_groups[i].xstart > row->pixel_groups[i - 1].xend);
|
assert(row->pixel_groups[i].xstart > row->pixel_groups[i - 1].xend);
|
||||||
}
|
}
|
||||||
if (i < row->pixel_groups_count - 1)
|
if (i < row->pixel_groups_count - 1) {
|
||||||
{
|
|
||||||
assert(row->pixel_groups[i].xend < row->pixel_groups[i + 1].xstart);
|
assert(row->pixel_groups[i].xend < row->pixel_groups[i + 1].xstart);
|
||||||
}
|
}
|
||||||
assert(row->pixel_groups[i].xend >= row->pixel_groups[i].xstart);
|
assert(row->pixel_groups[i].xend >= row->pixel_groups[i].xstart);
|
||||||
|
@ -328,22 +270,15 @@ double *PaintedGrid::getDataPointer(PaintedGridData *data, int x, int y, Painted
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Reset pixel if it had been added */
|
/* Reset pixel if it had been added */
|
||||||
if (added)
|
if (added) {
|
||||||
{
|
if (fallback) {
|
||||||
if (fallback)
|
double *dpointer = getDataPointer(fallback, x, y, NULL, false);
|
||||||
{
|
if (dpointer) {
|
||||||
double* dpointer = getDataPointer(fallback, x, y, NULL, false);
|
|
||||||
if (dpointer)
|
|
||||||
{
|
|
||||||
*pixel = *dpointer;
|
*pixel = *dpointer;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*pixel = getInitialValue(x, y);
|
*pixel = getInitialValue(x, y);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*pixel = getInitialValue(x, y);
|
*pixel = getInitialValue(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,9 @@ namespace definition {
|
||||||
*
|
*
|
||||||
* Grid cells are considered to be 1.0-sized.
|
* Grid cells are considered to be 1.0-sized.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT PaintedGrid: public DefinitionNode
|
class DEFINITIONSHARED_EXPORT PaintedGrid : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
PaintedGrid(DefinitionNode *parent = 0);
|
||||||
PaintedGrid(DefinitionNode *parent=0);
|
|
||||||
virtual ~PaintedGrid();
|
virtual ~PaintedGrid();
|
||||||
|
|
||||||
virtual void copy(DefinitionNode *destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
|
@ -67,7 +66,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Apply a brush stroke at a grid location (locating the brush center).
|
* Apply a brush stroke at a grid location (locating the brush center).
|
||||||
*/
|
*/
|
||||||
virtual void applyBrush(const PaintedGridBrush &brush, double x, double y, double force, bool commit=false);
|
virtual void applyBrush(const PaintedGridBrush &brush, double x, double y, double force, bool commit = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit previous brush strokes.
|
* Commit previous brush strokes.
|
||||||
|
@ -81,14 +80,13 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual double getInitialValue(double x, double y) const;
|
virtual double getInitialValue(double x, double y) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double *getDataPointer(PaintedGridData *data, int x, int y, PaintedGridData *fallback, bool grow) const;
|
double *getDataPointer(PaintedGridData *data, int x, int y, PaintedGridData *fallback, bool grow) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PaintedGridData *merged_data;
|
PaintedGridData *merged_data;
|
||||||
PaintedGridData *brush_data;
|
PaintedGridData *brush_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,11 @@
|
||||||
#include "NoiseGenerator.h"
|
#include "NoiseGenerator.h"
|
||||||
#include "PaintedGrid.h"
|
#include "PaintedGrid.h"
|
||||||
|
|
||||||
PaintedGridBrush::PaintedGridBrush(double hard_radius, double smoothed_size, double total_radius):
|
PaintedGridBrush::PaintedGridBrush(double hard_radius, double smoothed_size, double total_radius)
|
||||||
hard_radius(hard_radius), smoothed_size(smoothed_size), total_radius(total_radius)
|
: hard_radius(hard_radius), smoothed_size(smoothed_size), total_radius(total_radius) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGridBrush::getArea(double x, double y, int *xstart, int *ystart, int *xend, int *yend) const
|
void PaintedGridBrush::getArea(double x, double y, int *xstart, int *ystart, int *xend, int *yend) const {
|
||||||
{
|
|
||||||
double s = smoothed_size + hard_radius;
|
double s = smoothed_size + hard_radius;
|
||||||
|
|
||||||
*xstart = (int)floor(x - s);
|
*xstart = (int)floor(x - s);
|
||||||
|
@ -19,39 +17,31 @@ void PaintedGridBrush::getArea(double x, double y, int *xstart, int *ystart, int
|
||||||
*yend = (int)ceil(y + s);
|
*yend = (int)ceil(y + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGridBrush::getInfluence(double dx, double dy) const
|
double PaintedGridBrush::getInfluence(double dx, double dy) const {
|
||||||
{
|
|
||||||
double distance = sqrt(dx * dx + dy * dy);
|
double distance = sqrt(dx * dx + dy * dy);
|
||||||
|
|
||||||
if (distance > hard_radius)
|
if (distance > hard_radius) {
|
||||||
{
|
if (distance <= hard_radius + smoothed_size) {
|
||||||
if (distance <= hard_radius + smoothed_size)
|
|
||||||
{
|
|
||||||
return 1.0 - (distance - hard_radius) / smoothed_size;
|
return 1.0 - (distance - hard_radius) / smoothed_size;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGridBrush::getValue(const PaintedGrid *, double, double, double basevalue, double, double) const
|
double PaintedGridBrush::getValue(const PaintedGrid *, double, double, double basevalue, double, double) const {
|
||||||
{
|
|
||||||
return basevalue;
|
return basevalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGridBrushRaiseLower::getValue(const PaintedGrid *, double, double, double basevalue, double influence, double force) const
|
double PaintedGridBrushRaiseLower::getValue(const PaintedGrid *, double, double, double basevalue, double influence,
|
||||||
{
|
double force) const {
|
||||||
return basevalue + influence * force;
|
return basevalue + influence * force;
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGridBrushSmooth::getValue(const PaintedGrid *grid, double x, double y, double basevalue, double influence, double force) const
|
double PaintedGridBrushSmooth::getValue(const PaintedGrid *grid, double x, double y, double basevalue, double influence,
|
||||||
{
|
double force) const {
|
||||||
double ideal, factor;
|
double ideal, factor;
|
||||||
ideal = grid->getFinalValue((x + total_radius * 0.5), y);
|
ideal = grid->getFinalValue((x + total_radius * 0.5), y);
|
||||||
ideal += grid->getFinalValue((x - total_radius * 0.5), y);
|
ideal += grid->getFinalValue((x - total_radius * 0.5), y);
|
||||||
|
@ -59,26 +49,25 @@ double PaintedGridBrushSmooth::getValue(const PaintedGrid *grid, double x, doubl
|
||||||
ideal += grid->getFinalValue(x, (y + total_radius * 0.5));
|
ideal += grid->getFinalValue(x, (y + total_radius * 0.5));
|
||||||
ideal /= 4.0;
|
ideal /= 4.0;
|
||||||
factor = influence * force;
|
factor = influence * force;
|
||||||
if (factor > 1.0)
|
if (factor > 1.0) {
|
||||||
{
|
|
||||||
factor = 0.0;
|
factor = 0.0;
|
||||||
}
|
}
|
||||||
return basevalue + (ideal - basevalue) * factor;
|
return basevalue + (ideal - basevalue) * factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGridBrushAddNoise::getValue(const PaintedGrid *, double x, double y, double basevalue, double influence, double force) const
|
double PaintedGridBrushAddNoise::getValue(const PaintedGrid *, double x, double y, double basevalue, double influence,
|
||||||
{
|
double force) const {
|
||||||
return basevalue + generator->get2DTotal(x / total_radius, y / total_radius) * influence * force * total_radius;
|
return basevalue + generator->get2DTotal(x / total_radius, y / total_radius) * influence * force * total_radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGridBrushReset::getValue(const PaintedGrid *grid, double x, double y, double basevalue, double influence, double force) const
|
double PaintedGridBrushReset::getValue(const PaintedGrid *grid, double x, double y, double basevalue, double influence,
|
||||||
{
|
double force) const {
|
||||||
double ideal = grid->getInitialValue(x, y);
|
double ideal = grid->getInitialValue(x, y);
|
||||||
return basevalue + (ideal - basevalue) * influence * force;
|
return basevalue + (ideal - basevalue) * influence * force;
|
||||||
}
|
}
|
||||||
|
|
||||||
double PaintedGridBrushFlatten::getValue(const PaintedGrid *, double, double, double basevalue, double influence, double force) const
|
double PaintedGridBrushFlatten::getValue(const PaintedGrid *, double, double, double basevalue, double influence,
|
||||||
{
|
double force) const {
|
||||||
double ideal = target;
|
double ideal = target;
|
||||||
return basevalue + (ideal - basevalue) * influence * force;
|
return basevalue + (ideal - basevalue) * influence * force;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,8 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Base class for brushes that can be used to paint values on a PaintedGrid.
|
* Base class for brushes that can be used to paint values on a PaintedGrid.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT PaintedGridBrush
|
class DEFINITIONSHARED_EXPORT PaintedGridBrush {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
PaintedGridBrush(double hard_radius, double smoothed_size, double total_radius);
|
PaintedGridBrush(double hard_radius, double smoothed_size, double total_radius);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,9 +26,10 @@ public:
|
||||||
/**
|
/**
|
||||||
* Abstract method to reimplement to get the final value of a brush stroke at a given point.
|
* Abstract method to reimplement to get the final value of a brush stroke at a given point.
|
||||||
*/
|
*/
|
||||||
virtual double getValue(const PaintedGrid *grid, double x, double y, double basevalue, double influence, double force) const;
|
virtual double getValue(const PaintedGrid *grid, double x, double y, double basevalue, double influence,
|
||||||
|
double force) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
double hard_radius;
|
double hard_radius;
|
||||||
double smoothed_size;
|
double smoothed_size;
|
||||||
double total_radius;
|
double total_radius;
|
||||||
|
@ -38,57 +38,64 @@ protected:
|
||||||
/**
|
/**
|
||||||
* Brush able to raise or lower the grid value.
|
* Brush able to raise or lower the grid value.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT PaintedGridBrushRaiseLower: public PaintedGridBrush
|
class DEFINITIONSHARED_EXPORT PaintedGridBrushRaiseLower : public PaintedGridBrush {
|
||||||
{
|
public:
|
||||||
public:
|
PaintedGridBrushRaiseLower(const PaintedGridBrush &brush) : PaintedGridBrush(brush) {
|
||||||
PaintedGridBrushRaiseLower(const PaintedGridBrush &brush) : PaintedGridBrush(brush) {}
|
}
|
||||||
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence, double force) const override;
|
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence,
|
||||||
|
double force) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Brush able to smooth the value in an area.
|
* Brush able to smooth the value in an area.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT PaintedGridBrushSmooth: public PaintedGridBrush
|
class DEFINITIONSHARED_EXPORT PaintedGridBrushSmooth : public PaintedGridBrush {
|
||||||
{
|
public:
|
||||||
public:
|
PaintedGridBrushSmooth(const PaintedGridBrush &brush) : PaintedGridBrush(brush) {
|
||||||
PaintedGridBrushSmooth(const PaintedGridBrush &brush) : PaintedGridBrush(brush) {}
|
}
|
||||||
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence, double force) const override;
|
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence,
|
||||||
|
double force) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Brush able to add random fractal noise.
|
* Brush able to add random fractal noise.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT PaintedGridBrushAddNoise: public PaintedGridBrush
|
class DEFINITIONSHARED_EXPORT PaintedGridBrushAddNoise : public PaintedGridBrush {
|
||||||
{
|
public:
|
||||||
public:
|
PaintedGridBrushAddNoise(const PaintedGridBrush &brush, NoiseGenerator *generator)
|
||||||
PaintedGridBrushAddNoise(const PaintedGridBrush &brush, NoiseGenerator *generator) : PaintedGridBrush(brush), generator(generator) {}
|
: PaintedGridBrush(brush), generator(generator) {
|
||||||
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence, double force) const override;
|
}
|
||||||
private:
|
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence,
|
||||||
|
double force) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
NoiseGenerator *generator;
|
NoiseGenerator *generator;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Brush able to reset to initial value.
|
* Brush able to reset to initial value.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT PaintedGridBrushReset: public PaintedGridBrush
|
class DEFINITIONSHARED_EXPORT PaintedGridBrushReset : public PaintedGridBrush {
|
||||||
{
|
public:
|
||||||
public:
|
PaintedGridBrushReset(const PaintedGridBrush &brush) : PaintedGridBrush(brush) {
|
||||||
PaintedGridBrushReset(const PaintedGridBrush &brush) : PaintedGridBrush(brush) {}
|
}
|
||||||
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence, double force) const override;
|
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence,
|
||||||
|
double force) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Brush able to flatten to a specific value.
|
* Brush able to flatten to a specific value.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT PaintedGridBrushFlatten: public PaintedGridBrush
|
class DEFINITIONSHARED_EXPORT PaintedGridBrushFlatten : public PaintedGridBrush {
|
||||||
{
|
public:
|
||||||
public:
|
PaintedGridBrushFlatten(const PaintedGridBrush &brush, double target) : PaintedGridBrush(brush), target(target) {
|
||||||
PaintedGridBrushFlatten(const PaintedGridBrush &brush, double target) : PaintedGridBrush(brush), target(target) {}
|
}
|
||||||
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence, double force) const override;
|
double getValue(const PaintedGrid *grid, double x, double z, double basevalue, double influence,
|
||||||
private:
|
double force) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
double target;
|
double target;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,46 +3,40 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
|
|
||||||
PaintedGridData::PaintedGridData()
|
PaintedGridData::PaintedGridData() {
|
||||||
{
|
|
||||||
rows_count = 0;
|
rows_count = 0;
|
||||||
rows = (HeightMapRow *)malloc(sizeof(HeightMapRow));
|
rows = (HeightMapRow *)malloc(sizeof(HeightMapRow));
|
||||||
memsize = 0;
|
memsize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PaintedGridData::~PaintedGridData()
|
PaintedGridData::~PaintedGridData() {
|
||||||
{
|
|
||||||
clear();
|
clear();
|
||||||
free(rows);
|
free(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGridData::copy(PaintedGridData *destination) const
|
void PaintedGridData::copy(PaintedGridData *destination) const {
|
||||||
{
|
|
||||||
int i, j, n;
|
int i, j, n;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
destination->clear();
|
destination->clear();
|
||||||
|
|
||||||
destination->rows_count = this->rows_count;
|
destination->rows_count = this->rows_count;
|
||||||
if (destination->rows_count > 0)
|
if (destination->rows_count > 0) {
|
||||||
{
|
|
||||||
size = sizeof(HeightMapRow) * destination->rows_count;
|
size = sizeof(HeightMapRow) * destination->rows_count;
|
||||||
destination->rows = (HeightMapRow*)realloc(destination->rows, size);
|
destination->rows = (HeightMapRow *)realloc(destination->rows, size);
|
||||||
destination->memsize += size;
|
destination->memsize += size;
|
||||||
for (i = 0; i < destination->rows_count; i++)
|
for (i = 0; i < destination->rows_count; i++) {
|
||||||
{
|
|
||||||
destination->rows[i].y = this->rows[i].y;
|
destination->rows[i].y = this->rows[i].y;
|
||||||
destination->rows[i].pixel_groups_count = this->rows[i].pixel_groups_count;
|
destination->rows[i].pixel_groups_count = this->rows[i].pixel_groups_count;
|
||||||
size = sizeof(HeightMapPixelGroup) * destination->rows[i].pixel_groups_count;
|
size = sizeof(HeightMapPixelGroup) * destination->rows[i].pixel_groups_count;
|
||||||
destination->rows[i].pixel_groups = (HeightMapPixelGroup*)malloc(size);
|
destination->rows[i].pixel_groups = (HeightMapPixelGroup *)malloc(size);
|
||||||
destination->memsize += size;
|
destination->memsize += size;
|
||||||
for (j = 0; j < destination->rows[i].pixel_groups_count; j++)
|
for (j = 0; j < destination->rows[i].pixel_groups_count; j++) {
|
||||||
{
|
|
||||||
destination->rows[i].pixel_groups[j].xstart = this->rows[i].pixel_groups[j].xstart;
|
destination->rows[i].pixel_groups[j].xstart = this->rows[i].pixel_groups[j].xstart;
|
||||||
destination->rows[i].pixel_groups[j].xend = this->rows[i].pixel_groups[j].xend;
|
destination->rows[i].pixel_groups[j].xend = this->rows[i].pixel_groups[j].xend;
|
||||||
n = destination->rows[i].pixel_groups[j].xend - destination->rows[i].pixel_groups[j].xstart + 1;
|
n = destination->rows[i].pixel_groups[j].xend - destination->rows[i].pixel_groups[j].xstart + 1;
|
||||||
size = sizeof(double) * n;
|
size = sizeof(double) * n;
|
||||||
destination->rows[i].pixel_groups[j].height = (double*)malloc(size);
|
destination->rows[i].pixel_groups[j].height = (double *)malloc(size);
|
||||||
destination->memsize += size;
|
destination->memsize += size;
|
||||||
memcpy(destination->rows[i].pixel_groups[j].height, this->rows[i].pixel_groups[j].height, size);
|
memcpy(destination->rows[i].pixel_groups[j].height, this->rows[i].pixel_groups[j].height, size);
|
||||||
}
|
}
|
||||||
|
@ -50,56 +44,47 @@ void PaintedGridData::copy(PaintedGridData *destination) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGridData::save(PackStream *stream) const
|
void PaintedGridData::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
stream->write(&rows_count);
|
stream->write(&rows_count);
|
||||||
for (i = 0; i < rows_count; i++)
|
for (i = 0; i < rows_count; i++) {
|
||||||
{
|
|
||||||
stream->write(&rows[i].y);
|
stream->write(&rows[i].y);
|
||||||
stream->write(&rows[i].pixel_groups_count);
|
stream->write(&rows[i].pixel_groups_count);
|
||||||
for (j = 0; j < rows[i].pixel_groups_count; j++)
|
for (j = 0; j < rows[i].pixel_groups_count; j++) {
|
||||||
{
|
|
||||||
stream->write(&rows[i].pixel_groups[j].xstart);
|
stream->write(&rows[i].pixel_groups[j].xstart);
|
||||||
stream->write(&rows[i].pixel_groups[j].xend);
|
stream->write(&rows[i].pixel_groups[j].xend);
|
||||||
for (k = 0; k < rows[i].pixel_groups[j].xend - rows[i].pixel_groups[j].xstart; k++)
|
for (k = 0; k < rows[i].pixel_groups[j].xend - rows[i].pixel_groups[j].xstart; k++) {
|
||||||
{
|
|
||||||
stream->write(&rows[i].pixel_groups[j].height[k]);
|
stream->write(&rows[i].pixel_groups[j].height[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGridData::load(PackStream *stream)
|
void PaintedGridData::load(PackStream *stream) {
|
||||||
{
|
|
||||||
int i, j, k, n;
|
int i, j, k, n;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
stream->read(&rows_count);
|
stream->read(&rows_count);
|
||||||
if (rows_count > 0)
|
if (rows_count > 0) {
|
||||||
{
|
|
||||||
size = sizeof(HeightMapRow) * rows_count;
|
size = sizeof(HeightMapRow) * rows_count;
|
||||||
rows = (HeightMapRow*)realloc(rows, size);
|
rows = (HeightMapRow *)realloc(rows, size);
|
||||||
memsize += size;
|
memsize += size;
|
||||||
for (i = 0; i < rows_count; i++)
|
for (i = 0; i < rows_count; i++) {
|
||||||
{
|
|
||||||
stream->read(&rows[i].y);
|
stream->read(&rows[i].y);
|
||||||
stream->read(&rows[i].pixel_groups_count);
|
stream->read(&rows[i].pixel_groups_count);
|
||||||
size = sizeof(HeightMapPixelGroup) * rows[i].pixel_groups_count;
|
size = sizeof(HeightMapPixelGroup) * rows[i].pixel_groups_count;
|
||||||
rows[i].pixel_groups = (HeightMapPixelGroup*)malloc(size);
|
rows[i].pixel_groups = (HeightMapPixelGroup *)malloc(size);
|
||||||
memsize += size;
|
memsize += size;
|
||||||
for (j = 0; j < rows[i].pixel_groups_count; j++)
|
for (j = 0; j < rows[i].pixel_groups_count; j++) {
|
||||||
{
|
|
||||||
stream->read(&rows[i].pixel_groups[j].xstart);
|
stream->read(&rows[i].pixel_groups[j].xstart);
|
||||||
stream->read(&rows[i].pixel_groups[j].xend);
|
stream->read(&rows[i].pixel_groups[j].xend);
|
||||||
n = rows[i].pixel_groups[j].xend - rows[i].pixel_groups[j].xstart;
|
n = rows[i].pixel_groups[j].xend - rows[i].pixel_groups[j].xstart;
|
||||||
size = sizeof(double) * n;
|
size = sizeof(double) * n;
|
||||||
rows[i].pixel_groups[j].height = (double*)malloc(size);
|
rows[i].pixel_groups[j].height = (double *)malloc(size);
|
||||||
memsize += size;
|
memsize += size;
|
||||||
for (k = 0; k < n; k++)
|
for (k = 0; k < n; k++) {
|
||||||
{
|
|
||||||
stream->read(&rows[i].pixel_groups[j].height[k]);
|
stream->read(&rows[i].pixel_groups[j].height[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,13 +92,10 @@ void PaintedGridData::load(PackStream *stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedGridData::clear()
|
void PaintedGridData::clear() {
|
||||||
{
|
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i = 0; i < rows_count; i++)
|
for (i = 0; i < rows_count; i++) {
|
||||||
{
|
for (j = 0; j < rows[i].pixel_groups_count; j++) {
|
||||||
for (j = 0; j < rows[i].pixel_groups_count; j++)
|
|
||||||
{
|
|
||||||
free(rows[i].pixel_groups[j].height);
|
free(rows[i].pixel_groups[j].height);
|
||||||
}
|
}
|
||||||
free(rows[i].pixel_groups);
|
free(rows[i].pixel_groups);
|
||||||
|
|
|
@ -9,11 +9,10 @@ namespace definition {
|
||||||
/**
|
/**
|
||||||
* Internal storage class to hold data for a PaintedGrid.
|
* Internal storage class to hold data for a PaintedGrid.
|
||||||
*/
|
*/
|
||||||
class PaintedGridData
|
class PaintedGridData {
|
||||||
{
|
|
||||||
friend class PaintedGrid;
|
friend class PaintedGrid;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PaintedGridData();
|
PaintedGridData();
|
||||||
~PaintedGridData();
|
~PaintedGridData();
|
||||||
|
|
||||||
|
@ -26,28 +25,27 @@ public:
|
||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
inline bool hasData() const {return rows_count > 0;}
|
inline bool hasData() const {
|
||||||
|
return rows_count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
int xstart;
|
int xstart;
|
||||||
int xend;
|
int xend;
|
||||||
double* height;
|
double *height;
|
||||||
} HeightMapPixelGroup;
|
} HeightMapPixelGroup;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
int y;
|
int y;
|
||||||
int pixel_groups_count;
|
int pixel_groups_count;
|
||||||
HeightMapPixelGroup* pixel_groups;
|
HeightMapPixelGroup *pixel_groups;
|
||||||
} HeightMapRow;
|
} HeightMapRow;
|
||||||
|
|
||||||
int memsize;
|
int memsize;
|
||||||
int rows_count;
|
int rows_count;
|
||||||
HeightMapRow* rows;
|
HeightMapRow *rows;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,7 @@
|
||||||
static const double APP_HEADER = 19866544632.125;
|
static const double APP_HEADER = 19866544632.125;
|
||||||
static const int DATA_VERSION = 1;
|
static const int DATA_VERSION = 1;
|
||||||
|
|
||||||
Scenery::Scenery():
|
Scenery::Scenery() : DefinitionNode(NULL, "scenery", "scenery") {
|
||||||
DefinitionNode(NULL, "scenery", "scenery")
|
|
||||||
{
|
|
||||||
atmosphere = new AtmosphereDefinition(this);
|
atmosphere = new AtmosphereDefinition(this);
|
||||||
camera = new CameraDefinition(this);
|
camera = new CameraDefinition(this);
|
||||||
clouds = new CloudsDefinition(this);
|
clouds = new CloudsDefinition(this);
|
||||||
|
@ -28,21 +26,18 @@ Scenery::Scenery():
|
||||||
vegetation = new VegetationDefinition(this);
|
vegetation = new VegetationDefinition(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::validate()
|
void Scenery::validate() {
|
||||||
{
|
|
||||||
DefinitionNode::validate();
|
DefinitionNode::validate();
|
||||||
|
|
||||||
keepCameraAboveGround(camera);
|
keepCameraAboveGround(camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scenery::FileOperationResult Scenery::saveGlobal(const std::string &filepath) const
|
Scenery::FileOperationResult Scenery::saveGlobal(const std::string &filepath) const {
|
||||||
{
|
|
||||||
PackStream stream;
|
PackStream stream;
|
||||||
double app_header = (double)APP_HEADER;
|
double app_header = (double)APP_HEADER;
|
||||||
double version_header = (double)DATA_VERSION;
|
double version_header = (double)DATA_VERSION;
|
||||||
|
|
||||||
if (not stream.bindToFile(filepath, true))
|
if (not stream.bindToFile(filepath, true)) {
|
||||||
{
|
|
||||||
return FILE_OPERATION_IOERROR;
|
return FILE_OPERATION_IOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,25 +53,21 @@ Scenery::FileOperationResult Scenery::saveGlobal(const std::string &filepath) co
|
||||||
return FILE_OPERATION_OK;
|
return FILE_OPERATION_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scenery::FileOperationResult Scenery::loadGlobal(const std::string &filepath)
|
Scenery::FileOperationResult Scenery::loadGlobal(const std::string &filepath) {
|
||||||
{
|
|
||||||
PackStream stream;
|
PackStream stream;
|
||||||
double app_header, version_header;
|
double app_header, version_header;
|
||||||
|
|
||||||
if (not stream.bindToFile(filepath, false))
|
if (not stream.bindToFile(filepath, false)) {
|
||||||
{
|
|
||||||
return FILE_OPERATION_IOERROR;
|
return FILE_OPERATION_IOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.read(&app_header);
|
stream.read(&app_header);
|
||||||
if (app_header != APP_HEADER)
|
if (app_header != APP_HEADER) {
|
||||||
{
|
|
||||||
return FILE_OPERATION_APP_MISMATCH;
|
return FILE_OPERATION_APP_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.read(&version_header);
|
stream.read(&version_header);
|
||||||
if ((int)version_header != DATA_VERSION)
|
if ((int)version_header != DATA_VERSION) {
|
||||||
{
|
|
||||||
return FILE_OPERATION_VERSION_MISMATCH;
|
return FILE_OPERATION_VERSION_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,14 +78,12 @@ Scenery::FileOperationResult Scenery::loadGlobal(const std::string &filepath)
|
||||||
version_header = -1;
|
version_header = -1;
|
||||||
|
|
||||||
stream.read(&version_header);
|
stream.read(&version_header);
|
||||||
if ((int)version_header != DATA_VERSION)
|
if ((int)version_header != DATA_VERSION) {
|
||||||
{
|
|
||||||
return FILE_OPERATION_VERSION_MISMATCH;
|
return FILE_OPERATION_VERSION_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.read(&app_header);
|
stream.read(&app_header);
|
||||||
if (app_header != APP_HEADER)
|
if (app_header != APP_HEADER) {
|
||||||
{
|
|
||||||
return FILE_OPERATION_APP_MISMATCH;
|
return FILE_OPERATION_APP_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,15 +91,12 @@ Scenery::FileOperationResult Scenery::loadGlobal(const std::string &filepath)
|
||||||
return FILE_OPERATION_OK;
|
return FILE_OPERATION_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Scenery* Scenery::getScenery() const
|
const Scenery *Scenery::getScenery() const {
|
||||||
{
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::autoPreset(int seed)
|
void Scenery::autoPreset(int seed) {
|
||||||
{
|
if (!seed) {
|
||||||
if (!seed)
|
|
||||||
{
|
|
||||||
seed = time(NULL);
|
seed = time(NULL);
|
||||||
}
|
}
|
||||||
srand(seed);
|
srand(seed);
|
||||||
|
@ -130,84 +116,68 @@ void Scenery::autoPreset(int seed)
|
||||||
Logs::debug() << "New scenery generated from seed " << seed << std::endl;
|
Logs::debug() << "New scenery generated from seed " << seed << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::setAtmosphere(AtmosphereDefinition* atmosphere)
|
void Scenery::setAtmosphere(AtmosphereDefinition *atmosphere) {
|
||||||
{
|
|
||||||
atmosphere->copy(this->atmosphere);
|
atmosphere->copy(this->atmosphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::getAtmosphere(AtmosphereDefinition* atmosphere)
|
void Scenery::getAtmosphere(AtmosphereDefinition *atmosphere) {
|
||||||
{
|
|
||||||
this->atmosphere->copy(atmosphere);
|
this->atmosphere->copy(atmosphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::setCamera(CameraDefinition* camera)
|
void Scenery::setCamera(CameraDefinition *camera) {
|
||||||
{
|
|
||||||
camera->copy(this->camera);
|
camera->copy(this->camera);
|
||||||
keepCameraAboveGround(this->camera);
|
keepCameraAboveGround(this->camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::getCamera(CameraDefinition* camera)
|
void Scenery::getCamera(CameraDefinition *camera) {
|
||||||
{
|
|
||||||
this->camera->copy(camera);
|
this->camera->copy(camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::setClouds(CloudsDefinition* clouds)
|
void Scenery::setClouds(CloudsDefinition *clouds) {
|
||||||
{
|
|
||||||
clouds->copy(this->clouds);
|
clouds->copy(this->clouds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::getClouds(CloudsDefinition* clouds)
|
void Scenery::getClouds(CloudsDefinition *clouds) {
|
||||||
{
|
|
||||||
this->clouds->copy(clouds);
|
this->clouds->copy(clouds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::setTerrain(TerrainDefinition* terrain)
|
void Scenery::setTerrain(TerrainDefinition *terrain) {
|
||||||
{
|
|
||||||
terrain->copy(this->terrain);
|
terrain->copy(this->terrain);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::getTerrain(TerrainDefinition* terrain)
|
void Scenery::getTerrain(TerrainDefinition *terrain) {
|
||||||
{
|
|
||||||
this->terrain->copy(terrain);
|
this->terrain->copy(terrain);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::setTextures(TexturesDefinition* textures)
|
void Scenery::setTextures(TexturesDefinition *textures) {
|
||||||
{
|
|
||||||
textures->copy(this->textures);
|
textures->copy(this->textures);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::getTextures(TexturesDefinition* textures)
|
void Scenery::getTextures(TexturesDefinition *textures) {
|
||||||
{
|
|
||||||
this->textures->copy(textures);
|
this->textures->copy(textures);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::setVegetation(VegetationDefinition* vegetation)
|
void Scenery::setVegetation(VegetationDefinition *vegetation) {
|
||||||
{
|
|
||||||
vegetation->copy(this->vegetation);
|
vegetation->copy(this->vegetation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::getVegetation(VegetationDefinition* vegetation)
|
void Scenery::getVegetation(VegetationDefinition *vegetation) {
|
||||||
{
|
|
||||||
this->vegetation->copy(vegetation);
|
this->vegetation->copy(vegetation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::setWater(WaterDefinition* water)
|
void Scenery::setWater(WaterDefinition *water) {
|
||||||
{
|
|
||||||
water->copy(this->water);
|
water->copy(this->water);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::getWater(WaterDefinition* water)
|
void Scenery::getWater(WaterDefinition *water) {
|
||||||
{
|
|
||||||
this->water->copy(water);
|
this->water->copy(water);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scenery::keepCameraAboveGround(CameraDefinition* camera)
|
void Scenery::keepCameraAboveGround(CameraDefinition *camera) {
|
||||||
{
|
|
||||||
Vector3 camera_location = camera->getLocation();
|
Vector3 camera_location = camera->getLocation();
|
||||||
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, true, true) + 1.0;
|
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, true, true) + 1.0;
|
||||||
double water_height = 0.5;
|
double water_height = 0.5;
|
||||||
if (camera_location.y < water_height || camera_location.y < terrain_height)
|
if (camera_location.y < water_height || camera_location.y < terrain_height) {
|
||||||
{
|
|
||||||
double diff = ((water_height > terrain_height) ? water_height : terrain_height) - camera_location.y;
|
double diff = ((water_height > terrain_height) ? water_height : terrain_height) - camera_location.y;
|
||||||
camera->setLocation(camera_location.add(Vector3(0.0, diff, 0.0)));
|
camera->setLocation(camera_location.add(Vector3(0.0, diff, 0.0)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,8 @@ namespace definition {
|
||||||
*
|
*
|
||||||
* This class contains the whole scenery definition.
|
* This class contains the whole scenery definition.
|
||||||
*/
|
*/
|
||||||
class DEFINITIONSHARED_EXPORT Scenery: public DefinitionNode
|
class DEFINITIONSHARED_EXPORT Scenery : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FILE_OPERATION_OK,
|
FILE_OPERATION_OK,
|
||||||
FILE_OPERATION_IOERROR,
|
FILE_OPERATION_IOERROR,
|
||||||
|
@ -23,9 +22,9 @@ public:
|
||||||
FILE_OPERATION_VERSION_MISMATCH
|
FILE_OPERATION_VERSION_MISMATCH
|
||||||
} FileOperationResult;
|
} FileOperationResult;
|
||||||
|
|
||||||
typedef void (*SceneryCustomDataCallback)(PackStream* stream, void* data);
|
typedef void (*SceneryCustomDataCallback)(PackStream *stream, void *data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Scenery();
|
Scenery();
|
||||||
|
|
||||||
virtual void validate() override;
|
virtual void validate() override;
|
||||||
|
@ -33,50 +32,63 @@ public:
|
||||||
FileOperationResult saveGlobal(const std::string &filepath) const;
|
FileOperationResult saveGlobal(const std::string &filepath) const;
|
||||||
FileOperationResult loadGlobal(const std::string &filepath);
|
FileOperationResult loadGlobal(const std::string &filepath);
|
||||||
|
|
||||||
virtual const Scenery* getScenery() const override;
|
virtual const Scenery *getScenery() const override;
|
||||||
|
|
||||||
void autoPreset(int seed=0);
|
void autoPreset(int seed = 0);
|
||||||
|
|
||||||
void setAtmosphere(AtmosphereDefinition* atmosphere);
|
void setAtmosphere(AtmosphereDefinition *atmosphere);
|
||||||
inline AtmosphereDefinition* getAtmosphere() const {return atmosphere;}
|
inline AtmosphereDefinition *getAtmosphere() const {
|
||||||
void getAtmosphere(AtmosphereDefinition* atmosphere);
|
return atmosphere;
|
||||||
|
}
|
||||||
|
void getAtmosphere(AtmosphereDefinition *atmosphere);
|
||||||
|
|
||||||
void setCamera(CameraDefinition* camera);
|
void setCamera(CameraDefinition *camera);
|
||||||
inline CameraDefinition* getCamera() const {return camera;}
|
inline CameraDefinition *getCamera() const {
|
||||||
void getCamera(CameraDefinition* camera);
|
return camera;
|
||||||
|
}
|
||||||
|
void getCamera(CameraDefinition *camera);
|
||||||
|
|
||||||
void setClouds(CloudsDefinition* clouds);
|
void setClouds(CloudsDefinition *clouds);
|
||||||
inline CloudsDefinition* getClouds() const {return clouds;}
|
inline CloudsDefinition *getClouds() const {
|
||||||
void getClouds(CloudsDefinition* clouds);
|
return clouds;
|
||||||
|
}
|
||||||
|
void getClouds(CloudsDefinition *clouds);
|
||||||
|
|
||||||
void setTerrain(TerrainDefinition* terrain);
|
void setTerrain(TerrainDefinition *terrain);
|
||||||
inline TerrainDefinition* getTerrain() const {return terrain;}
|
inline TerrainDefinition *getTerrain() const {
|
||||||
void getTerrain(TerrainDefinition* terrain);
|
return terrain;
|
||||||
|
}
|
||||||
|
void getTerrain(TerrainDefinition *terrain);
|
||||||
|
|
||||||
void setTextures(TexturesDefinition* textures);
|
void setTextures(TexturesDefinition *textures);
|
||||||
inline TexturesDefinition* getTextures() const {return textures;}
|
inline TexturesDefinition *getTextures() const {
|
||||||
void getTextures(TexturesDefinition* textures);
|
return textures;
|
||||||
|
}
|
||||||
|
void getTextures(TexturesDefinition *textures);
|
||||||
|
|
||||||
void setVegetation(VegetationDefinition* Vegetation);
|
void setVegetation(VegetationDefinition *Vegetation);
|
||||||
inline VegetationDefinition* getVegetation() const {return vegetation;}
|
inline VegetationDefinition *getVegetation() const {
|
||||||
void getVegetation(VegetationDefinition* Vegetation);
|
return vegetation;
|
||||||
|
}
|
||||||
|
void getVegetation(VegetationDefinition *Vegetation);
|
||||||
|
|
||||||
void setWater(WaterDefinition* water);
|
void setWater(WaterDefinition *water);
|
||||||
inline WaterDefinition* getWater() const {return water;}
|
inline WaterDefinition *getWater() const {
|
||||||
void getWater(WaterDefinition* water);
|
return water;
|
||||||
|
}
|
||||||
|
void getWater(WaterDefinition *water);
|
||||||
|
|
||||||
void keepCameraAboveGround(CameraDefinition* camera);
|
void keepCameraAboveGround(CameraDefinition *camera);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AtmosphereDefinition* atmosphere;
|
AtmosphereDefinition *atmosphere;
|
||||||
CameraDefinition* camera;
|
CameraDefinition *camera;
|
||||||
CloudsDefinition* clouds;
|
CloudsDefinition *clouds;
|
||||||
TerrainDefinition* terrain;
|
TerrainDefinition *terrain;
|
||||||
TexturesDefinition* textures;
|
TexturesDefinition *textures;
|
||||||
VegetationDefinition* vegetation;
|
VegetationDefinition *vegetation;
|
||||||
WaterDefinition* water;
|
WaterDefinition *water;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,10 @@
|
||||||
|
|
||||||
static SurfaceMaterial DEFAULT;
|
static SurfaceMaterial DEFAULT;
|
||||||
|
|
||||||
SurfaceMaterial::SurfaceMaterial():
|
SurfaceMaterial::SurfaceMaterial() : SurfaceMaterial(COLOR_BLACK) {
|
||||||
SurfaceMaterial(COLOR_BLACK)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceMaterial::SurfaceMaterial(const Color &color)
|
SurfaceMaterial::SurfaceMaterial(const Color &color) {
|
||||||
{
|
|
||||||
base = new Color(color);
|
base = new Color(color);
|
||||||
hardness = 0.5;
|
hardness = 0.5;
|
||||||
reflection = 0.0;
|
reflection = 0.0;
|
||||||
|
@ -19,32 +16,26 @@ SurfaceMaterial::SurfaceMaterial(const Color &color)
|
||||||
receive_shadows = 1.0;
|
receive_shadows = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceMaterial::SurfaceMaterial(const SurfaceMaterial &other):
|
SurfaceMaterial::SurfaceMaterial(const SurfaceMaterial &other) : SurfaceMaterial(COLOR_BLACK) {
|
||||||
SurfaceMaterial(COLOR_BLACK)
|
|
||||||
{
|
|
||||||
other.copy(this);
|
other.copy(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceMaterial::~SurfaceMaterial()
|
SurfaceMaterial::~SurfaceMaterial() {
|
||||||
{
|
|
||||||
delete base;
|
delete base;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SurfaceMaterial &SurfaceMaterial::getDefault()
|
const SurfaceMaterial &SurfaceMaterial::getDefault() {
|
||||||
{
|
|
||||||
return DEFAULT;
|
return DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceMaterial::setColor(double r, double g, double b, double a)
|
void SurfaceMaterial::setColor(double r, double g, double b, double a) {
|
||||||
{
|
|
||||||
base->r = r;
|
base->r = r;
|
||||||
base->g = g;
|
base->g = g;
|
||||||
base->b = b;
|
base->b = b;
|
||||||
base->a = a;
|
base->a = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceMaterial::save(PackStream* stream) const
|
void SurfaceMaterial::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
base->save(stream);
|
base->save(stream);
|
||||||
|
|
||||||
stream->write(&hardness);
|
stream->write(&hardness);
|
||||||
|
@ -54,8 +45,7 @@ void SurfaceMaterial::save(PackStream* stream) const
|
||||||
stream->write(&receive_shadows);
|
stream->write(&receive_shadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceMaterial::load(PackStream* stream)
|
void SurfaceMaterial::load(PackStream *stream) {
|
||||||
{
|
|
||||||
base->load(stream);
|
base->load(stream);
|
||||||
|
|
||||||
stream->read(&hardness);
|
stream->read(&hardness);
|
||||||
|
@ -65,8 +55,7 @@ void SurfaceMaterial::load(PackStream* stream)
|
||||||
stream->read(&receive_shadows);
|
stream->read(&receive_shadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceMaterial::copy(SurfaceMaterial *destination) const
|
void SurfaceMaterial::copy(SurfaceMaterial *destination) const {
|
||||||
{
|
|
||||||
*destination->base = *base;
|
*destination->base = *base;
|
||||||
destination->hardness = hardness;
|
destination->hardness = hardness;
|
||||||
destination->reflection = reflection;
|
destination->reflection = reflection;
|
||||||
|
@ -75,6 +64,5 @@ void SurfaceMaterial::copy(SurfaceMaterial *destination) const
|
||||||
destination->validate();
|
destination->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceMaterial::validate()
|
void SurfaceMaterial::validate() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT SurfaceMaterial
|
class DEFINITIONSHARED_EXPORT SurfaceMaterial {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
SurfaceMaterial();
|
SurfaceMaterial();
|
||||||
SurfaceMaterial(const Color &color);
|
SurfaceMaterial(const Color &color);
|
||||||
SurfaceMaterial(const SurfaceMaterial &other);
|
SurfaceMaterial(const SurfaceMaterial &other);
|
||||||
|
@ -23,7 +22,7 @@ public:
|
||||||
void copy(SurfaceMaterial *destination) const;
|
void copy(SurfaceMaterial *destination) const;
|
||||||
void validate();
|
void validate();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Color *base;
|
Color *base;
|
||||||
|
|
||||||
double hardness;
|
double hardness;
|
||||||
|
@ -32,7 +31,6 @@ public:
|
||||||
|
|
||||||
double receive_shadows;
|
double receive_shadows;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
|
|
||||||
TerrainDefinition::TerrainDefinition(DefinitionNode* parent):
|
TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(parent, "terrain", "terrain") {
|
||||||
DefinitionNode(parent, "terrain", "terrain")
|
|
||||||
{
|
|
||||||
height = 1.0;
|
height = 1.0;
|
||||||
shadow_smoothing = 0.0;
|
shadow_smoothing = 0.0;
|
||||||
|
|
||||||
|
@ -20,17 +18,14 @@ TerrainDefinition::TerrainDefinition(DefinitionNode* parent):
|
||||||
_height_noise = new NoiseGenerator;
|
_height_noise = new NoiseGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainDefinition::~TerrainDefinition()
|
TerrainDefinition::~TerrainDefinition() {
|
||||||
{
|
|
||||||
delete _height_noise;
|
delete _height_noise;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::validate()
|
void TerrainDefinition::validate() {
|
||||||
{
|
|
||||||
_height_noise->validate();
|
_height_noise->validate();
|
||||||
|
|
||||||
if (height < 1.0)
|
if (height < 1.0) {
|
||||||
{
|
|
||||||
height = 1.0;
|
height = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +38,8 @@ void TerrainDefinition::validate()
|
||||||
has_painting = height_map->hasPainting();
|
has_painting = height_map->hasPainting();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::copy(DefinitionNode* _destination) const
|
void TerrainDefinition::copy(DefinitionNode *_destination) const {
|
||||||
{
|
TerrainDefinition *destination = (TerrainDefinition *)_destination;
|
||||||
TerrainDefinition* destination = (TerrainDefinition*)_destination;
|
|
||||||
|
|
||||||
destination->height = height;
|
destination->height = height;
|
||||||
destination->shadow_smoothing = shadow_smoothing;
|
destination->shadow_smoothing = shadow_smoothing;
|
||||||
|
@ -57,8 +51,7 @@ void TerrainDefinition::copy(DefinitionNode* _destination) const
|
||||||
destination->validate();
|
destination->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::save(PackStream* stream) const
|
void TerrainDefinition::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
DefinitionNode::save(stream);
|
DefinitionNode::save(stream);
|
||||||
|
|
||||||
stream->write(&height);
|
stream->write(&height);
|
||||||
|
@ -66,8 +59,7 @@ void TerrainDefinition::save(PackStream* stream) const
|
||||||
_height_noise->save(stream);
|
_height_noise->save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::load(PackStream* stream)
|
void TerrainDefinition::load(PackStream *stream) {
|
||||||
{
|
|
||||||
DefinitionNode::load(stream);
|
DefinitionNode::load(stream);
|
||||||
|
|
||||||
stream->read(&height);
|
stream->read(&height);
|
||||||
|
@ -77,44 +69,36 @@ void TerrainDefinition::load(PackStream* stream)
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
double TerrainDefinition::getGridHeight(int x, int z, bool with_painting)
|
double TerrainDefinition::getGridHeight(int x, int z, bool with_painting) {
|
||||||
{
|
|
||||||
double h;
|
double h;
|
||||||
|
|
||||||
if (!with_painting || !has_painting || !height_map->getGridValue(x, z, &h))
|
if (!with_painting || !has_painting || !height_map->getGridValue(x, z, &h)) {
|
||||||
{
|
|
||||||
h = _height_noise->get2DTotal((double)x, (double)z);
|
h = _height_noise->get2DTotal((double)x, (double)z);
|
||||||
}
|
}
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
double TerrainDefinition::getInterpolatedHeight(double x, double z, bool scaled, bool with_painting, bool water_offset)
|
double TerrainDefinition::getInterpolatedHeight(double x, double z, bool scaled, bool with_painting,
|
||||||
{
|
bool water_offset) {
|
||||||
double h;
|
double h;
|
||||||
|
|
||||||
if (!with_painting || !has_painting || !height_map->getInterpolatedValue(x, z, &h))
|
if (!with_painting || !has_painting || !height_map->getInterpolatedValue(x, z, &h)) {
|
||||||
{
|
|
||||||
h = _height_noise->get2DTotal(x, z);
|
h = _height_noise->get2DTotal(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scaled)
|
if (scaled) {
|
||||||
{
|
|
||||||
return (water_offset ? (h - water_height->getValue()) : h) * height;
|
return (water_offset ? (h - water_height->getValue()) : h) * height;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double TerrainDefinition::getWaterOffset() const
|
double TerrainDefinition::getWaterOffset() const {
|
||||||
{
|
|
||||||
return -water_height->getValue() * height;
|
return -water_height->getValue() * height;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightInfo TerrainDefinition::getHeightInfo()
|
HeightInfo TerrainDefinition::getHeightInfo() {
|
||||||
{
|
|
||||||
HeightInfo result;
|
HeightInfo result;
|
||||||
|
|
||||||
result.min_height = _min_height;
|
result.min_height = _min_height;
|
||||||
|
@ -124,16 +108,13 @@ HeightInfo TerrainDefinition::getHeightInfo()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long TerrainDefinition::getMemoryStats()
|
unsigned long TerrainDefinition::getMemoryStats() {
|
||||||
{
|
|
||||||
return height_map->getMemoryStats();
|
return height_map->getMemoryStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::applyPreset(TerrainPreset preset)
|
void TerrainDefinition::applyPreset(TerrainPreset preset) {
|
||||||
{
|
|
||||||
int resolution = 8;
|
int resolution = 8;
|
||||||
switch (preset)
|
switch (preset) {
|
||||||
{
|
|
||||||
case TERRAIN_PRESET_STANDARD:
|
case TERRAIN_PRESET_STANDARD:
|
||||||
_height_noise->randomizeOffsets();
|
_height_noise->randomizeOffsets();
|
||||||
_height_noise->clearLevels();
|
_height_noise->clearLevels();
|
||||||
|
|
|
@ -8,56 +8,52 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
double min_height;
|
double min_height;
|
||||||
double max_height;
|
double max_height;
|
||||||
double base_height;
|
double base_height;
|
||||||
} HeightInfo;
|
} HeightInfo;
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode
|
class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode {
|
||||||
{
|
public:
|
||||||
public:
|
TerrainDefinition(DefinitionNode *parent);
|
||||||
TerrainDefinition(DefinitionNode* parent);
|
|
||||||
virtual ~TerrainDefinition();
|
virtual ~TerrainDefinition();
|
||||||
|
|
||||||
virtual void save(PackStream* stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream* stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
|
|
||||||
virtual void copy(DefinitionNode* destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
virtual void validate() override;
|
virtual void validate() override;
|
||||||
|
|
||||||
inline FloatNode *propWaterHeight() const {return water_height;}
|
inline FloatNode *propWaterHeight() const {
|
||||||
|
return water_height;
|
||||||
|
}
|
||||||
|
|
||||||
double getGridHeight(int x, int z, bool with_painting);
|
double getGridHeight(int x, int z, bool with_painting);
|
||||||
double getInterpolatedHeight(double x, double z, bool scaled, bool with_painting, bool water_offset=true);
|
double getInterpolatedHeight(double x, double z, bool scaled, bool with_painting, bool water_offset = true);
|
||||||
double getWaterOffset() const;
|
double getWaterOffset() const;
|
||||||
unsigned long getMemoryStats();
|
unsigned long getMemoryStats();
|
||||||
HeightInfo getHeightInfo();
|
HeightInfo getHeightInfo();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef enum
|
typedef enum { TERRAIN_PRESET_STANDARD } TerrainPreset;
|
||||||
{
|
|
||||||
TERRAIN_PRESET_STANDARD
|
|
||||||
} TerrainPreset;
|
|
||||||
void applyPreset(TerrainPreset preset);
|
void applyPreset(TerrainPreset preset);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
double height;
|
double height;
|
||||||
double shadow_smoothing;
|
double shadow_smoothing;
|
||||||
|
|
||||||
TerrainHeightMap* height_map;
|
TerrainHeightMap *height_map;
|
||||||
bool has_painting;
|
bool has_painting;
|
||||||
|
|
||||||
double _detail;
|
double _detail;
|
||||||
NoiseGenerator* _height_noise;
|
NoiseGenerator *_height_noise;
|
||||||
double _min_height;
|
double _min_height;
|
||||||
double _max_height;
|
double _max_height;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FloatNode *water_height;
|
FloatNode *water_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,64 +3,55 @@
|
||||||
#include "TerrainDefinition.h"
|
#include "TerrainDefinition.h"
|
||||||
#include "PaintedGridBrush.h"
|
#include "PaintedGridBrush.h"
|
||||||
|
|
||||||
TerrainHeightMap::TerrainHeightMap(TerrainDefinition* terrain):
|
TerrainHeightMap::TerrainHeightMap(TerrainDefinition *terrain) : PaintedGrid(terrain), terrain(terrain) {
|
||||||
PaintedGrid(terrain), terrain(terrain)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::copy(DefinitionNode* _destination) const
|
void TerrainHeightMap::copy(DefinitionNode *_destination) const {
|
||||||
{
|
TerrainHeightMap *destination = (TerrainHeightMap *)_destination;
|
||||||
TerrainHeightMap* destination = (TerrainHeightMap*)_destination;
|
|
||||||
|
|
||||||
destination->terrain = terrain;
|
destination->terrain = terrain;
|
||||||
|
|
||||||
PaintedGrid::copy(destination);
|
PaintedGrid::copy(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
double TerrainHeightMap::getInitialValue(double x, double y) const
|
double TerrainHeightMap::getInitialValue(double x, double y) const {
|
||||||
{
|
|
||||||
return terrain->getInterpolatedHeight(x, y, false, false);
|
return terrain->getInterpolatedHeight(x, y, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::brushElevation(const PaintedGridBrush &brush, double x, double y, double value, bool commit)
|
void TerrainHeightMap::brushElevation(const PaintedGridBrush &brush, double x, double y, double value, bool commit) {
|
||||||
{
|
|
||||||
PaintedGridBrushRaiseLower sbrush(brush);
|
PaintedGridBrushRaiseLower sbrush(brush);
|
||||||
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::brushFlatten(const PaintedGridBrush &brush, double x, double y, double height, double force, bool commit)
|
void TerrainHeightMap::brushFlatten(const PaintedGridBrush &brush, double x, double y, double height, double force,
|
||||||
{
|
bool commit) {
|
||||||
PaintedGridBrushFlatten sbrush(brush, height);
|
PaintedGridBrushFlatten sbrush(brush, height);
|
||||||
applyBrush(sbrush, x, y, force / terrain->height, commit);
|
applyBrush(sbrush, x, y, force / terrain->height, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::brushSmooth(const PaintedGridBrush &brush, double x, double y, double value, bool commit)
|
void TerrainHeightMap::brushSmooth(const PaintedGridBrush &brush, double x, double y, double value, bool commit) {
|
||||||
{
|
|
||||||
PaintedGridBrushSmooth sbrush(brush);
|
PaintedGridBrushSmooth sbrush(brush);
|
||||||
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::brushAddNoise(const PaintedGridBrush &brush, double x, double y, NoiseGenerator* generator, double value, bool commit)
|
void TerrainHeightMap::brushAddNoise(const PaintedGridBrush &brush, double x, double y, NoiseGenerator *generator,
|
||||||
{
|
double value, bool commit) {
|
||||||
PaintedGridBrushAddNoise sbrush(brush, generator);
|
PaintedGridBrushAddNoise sbrush(brush, generator);
|
||||||
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::brushReset(const PaintedGridBrush &brush, double x, double y, double value, bool commit)
|
void TerrainHeightMap::brushReset(const PaintedGridBrush &brush, double x, double y, double value, bool commit) {
|
||||||
{
|
|
||||||
PaintedGridBrushReset sbrush(brush);
|
PaintedGridBrushReset sbrush(brush);
|
||||||
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::clearPainting()
|
void TerrainHeightMap::clearPainting() {
|
||||||
{
|
|
||||||
PaintedGrid::clearPainting();
|
PaintedGrid::clearPainting();
|
||||||
|
|
||||||
terrain->validate();
|
terrain->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::endBrushStroke()
|
void TerrainHeightMap::endBrushStroke() {
|
||||||
{
|
|
||||||
PaintedGrid::endBrushStroke();
|
PaintedGrid::endBrushStroke();
|
||||||
|
|
||||||
terrain->validate();
|
terrain->validate();
|
||||||
|
|
|
@ -8,30 +8,32 @@
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace definition {
|
namespace definition {
|
||||||
|
|
||||||
class DEFINITIONSHARED_EXPORT TerrainHeightMap : public PaintedGrid
|
class DEFINITIONSHARED_EXPORT TerrainHeightMap : public PaintedGrid {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
TerrainHeightMap(TerrainDefinition *terrain);
|
TerrainHeightMap(TerrainDefinition *terrain);
|
||||||
|
|
||||||
virtual void copy(DefinitionNode *destination) const override;
|
virtual void copy(DefinitionNode *destination) const override;
|
||||||
|
|
||||||
inline TerrainDefinition* getTerrain() const {return terrain;}
|
inline TerrainDefinition *getTerrain() const {
|
||||||
|
return terrain;
|
||||||
|
}
|
||||||
|
|
||||||
virtual double getInitialValue(double x, double y) const override;
|
virtual double getInitialValue(double x, double y) const override;
|
||||||
|
|
||||||
void brushElevation(const PaintedGridBrush &brush, double x, double y, double value, bool commit=false);
|
void brushElevation(const PaintedGridBrush &brush, double x, double y, double value, bool commit = false);
|
||||||
void brushSmooth(const PaintedGridBrush &brush, double x, double y, double value, bool commit=false);
|
void brushSmooth(const PaintedGridBrush &brush, double x, double y, double value, bool commit = false);
|
||||||
void brushAddNoise(const PaintedGridBrush &brush, double x, double y, NoiseGenerator* generator, double value, bool commit=false);
|
void brushAddNoise(const PaintedGridBrush &brush, double x, double y, NoiseGenerator *generator, double value,
|
||||||
void brushReset(const PaintedGridBrush &brush, double x, double y, double value, bool commit=false);
|
bool commit = false);
|
||||||
void brushFlatten(const PaintedGridBrush &brush, double x, double y, double height, double force, bool commit=false);
|
void brushReset(const PaintedGridBrush &brush, double x, double y, double value, bool commit = false);
|
||||||
|
void brushFlatten(const PaintedGridBrush &brush, double x, double y, double height, double force,
|
||||||
|
bool commit = false);
|
||||||
|
|
||||||
virtual void clearPainting() override;
|
virtual void clearPainting() override;
|
||||||
virtual void endBrushStroke() override;
|
virtual void endBrushStroke() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TerrainDefinition* terrain;
|
TerrainDefinition *terrain;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,8 @@
|
||||||
#include "TerrainDefinition.h"
|
#include "TerrainDefinition.h"
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
|
|
||||||
TextureLayerDefinition::TextureLayerDefinition(DefinitionNode* parent):
|
TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent)
|
||||||
DefinitionNode(parent, "texture", "texturelayer")
|
: DefinitionNode(parent, "texture", "texturelayer") {
|
||||||
{
|
|
||||||
terrain_zone = new Zone;
|
terrain_zone = new Zone;
|
||||||
_displacement_noise = new NoiseGenerator;
|
_displacement_noise = new NoiseGenerator;
|
||||||
_detail_noise = new NoiseGenerator;
|
_detail_noise = new NoiseGenerator;
|
||||||
|
@ -20,20 +19,17 @@ TextureLayerDefinition::TextureLayerDefinition(DefinitionNode* parent):
|
||||||
displacement_scaling = 1.0;
|
displacement_scaling = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureLayerDefinition::~TextureLayerDefinition()
|
TextureLayerDefinition::~TextureLayerDefinition() {
|
||||||
{
|
|
||||||
delete terrain_zone;
|
delete terrain_zone;
|
||||||
delete _displacement_noise;
|
delete _displacement_noise;
|
||||||
delete _detail_noise;
|
delete _detail_noise;
|
||||||
delete material;
|
delete material;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::validate()
|
void TextureLayerDefinition::validate() {
|
||||||
{
|
|
||||||
DefinitionNode::validate();
|
DefinitionNode::validate();
|
||||||
|
|
||||||
if (displacement_scaling < 0.000001)
|
if (displacement_scaling < 0.000001) {
|
||||||
{
|
|
||||||
displacement_scaling = 0.000001;
|
displacement_scaling = 0.000001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,20 +46,18 @@ void TextureLayerDefinition::validate()
|
||||||
material->validate();
|
material->validate();
|
||||||
|
|
||||||
/* Update zone height range */
|
/* Update zone height range */
|
||||||
const Scenery* scenery = getScenery();
|
const Scenery *scenery = getScenery();
|
||||||
if (scenery)
|
if (scenery) {
|
||||||
{
|
TerrainDefinition *terrain = scenery->getTerrain();
|
||||||
TerrainDefinition* terrain = scenery->getTerrain();
|
|
||||||
HeightInfo height_info = terrain->getHeightInfo();
|
HeightInfo height_info = terrain->getHeightInfo();
|
||||||
terrain_zone->setRelativeHeight(height_info.min_height, height_info.base_height, height_info.max_height);
|
terrain_zone->setRelativeHeight(height_info.min_height, height_info.base_height, height_info.max_height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::copy(DefinitionNode *_destination) const
|
void TextureLayerDefinition::copy(DefinitionNode *_destination) const {
|
||||||
{
|
|
||||||
DefinitionNode::copy(_destination);
|
DefinitionNode::copy(_destination);
|
||||||
|
|
||||||
TextureLayerDefinition* destination = (TextureLayerDefinition*)_destination;
|
TextureLayerDefinition *destination = (TextureLayerDefinition *)_destination;
|
||||||
|
|
||||||
terrain_zone->copy(destination->terrain_zone);
|
terrain_zone->copy(destination->terrain_zone);
|
||||||
|
|
||||||
|
@ -76,8 +70,7 @@ void TextureLayerDefinition::copy(DefinitionNode *_destination) const
|
||||||
_detail_noise->copy(destination->_detail_noise);
|
_detail_noise->copy(destination->_detail_noise);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::save(PackStream* stream) const
|
void TextureLayerDefinition::save(PackStream *stream) const {
|
||||||
{
|
|
||||||
DefinitionNode::save(stream);
|
DefinitionNode::save(stream);
|
||||||
|
|
||||||
terrain_zone->save(stream);
|
terrain_zone->save(stream);
|
||||||
|
@ -90,8 +83,7 @@ void TextureLayerDefinition::save(PackStream* stream) const
|
||||||
_detail_noise->save(stream);
|
_detail_noise->save(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::load(PackStream* stream)
|
void TextureLayerDefinition::load(PackStream *stream) {
|
||||||
{
|
|
||||||
DefinitionNode::load(stream);
|
DefinitionNode::load(stream);
|
||||||
|
|
||||||
terrain_zone->load(stream);
|
terrain_zone->load(stream);
|
||||||
|
@ -104,15 +96,13 @@ void TextureLayerDefinition::load(PackStream* stream)
|
||||||
_detail_noise->load(stream);
|
_detail_noise->load(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::applyPreset(TextureLayerPreset preset)
|
void TextureLayerDefinition::applyPreset(TextureLayerPreset preset) {
|
||||||
{
|
|
||||||
_displacement_noise->randomizeOffsets();
|
_displacement_noise->randomizeOffsets();
|
||||||
_detail_noise->randomizeOffsets();
|
_detail_noise->randomizeOffsets();
|
||||||
|
|
||||||
terrain_zone->clear();
|
terrain_zone->clear();
|
||||||
|
|
||||||
switch (preset)
|
switch (preset) {
|
||||||
{
|
|
||||||
case TEXTURES_LAYER_PRESET_MUD:
|
case TEXTURES_LAYER_PRESET_MUD:
|
||||||
displacement_height = 0.02;
|
displacement_height = 0.02;
|
||||||
displacement_scaling = 3.0;
|
displacement_scaling = 3.0;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue