Added ColorNode

This commit is contained in:
Michaël Lemaire 2015-12-16 01:32:25 +01:00
parent 990d28d09d
commit b376d7f8e9
15 changed files with 327 additions and 46 deletions

View file

@ -35,7 +35,12 @@ class BASICSSHARED_EXPORT Color {
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;
inline bool operator==(const Color &other) const {
return r == other.r and g == other.g and b == other.b and a == other.a;
}
public: public:
// TODO Make private
double r; double r;
double g; double g;
double b; double b;
@ -52,11 +57,4 @@ BASICSSHARED_EXPORT extern const Color COLOR_GREY;
} }
} }
// Inlining
#if PAYSAGES_USE_INLINING
#ifndef COLOR_INLINE_CPP
#include "Color.inline.cpp"
#endif
#endif
#endif // COLOR_H #endif // COLOR_H

View file

@ -0,0 +1,13 @@
#include "ColorDiff.h"
ColorDiff::ColorDiff(const DefinitionNode *node, const Color &oldvalue, const Color &newvalue)
: DefinitionDiff(node), oldvalue(oldvalue), newvalue(newvalue) {
}
ColorDiff::ColorDiff(const ColorDiff *other, const Color &oldvalue, const Color &newvalue)
: DefinitionDiff(other), oldvalue(oldvalue), newvalue(newvalue) {
}
DefinitionDiff *ColorDiff::newReversed() const {
return new ColorDiff(this, newvalue, oldvalue);
}

View file

@ -0,0 +1,36 @@
#ifndef COLORDIFF_H
#define COLORDIFF_H
#include "definition_global.h"
#include "DefinitionDiff.h"
#include "Color.h"
namespace paysages {
namespace definition {
/**
* Diff for a ColorNode.
*/
class DEFINITIONSHARED_EXPORT ColorDiff : public DefinitionDiff {
public:
ColorDiff(const DefinitionNode *node, const Color &oldvalue, const Color &newvalue);
ColorDiff(const ColorDiff *other, const Color &oldvalue, const Color &newvalue);
inline const Color &getOldValue() const {
return oldvalue;
}
inline const Color &getNewValue() const {
return newvalue;
}
virtual DefinitionDiff *newReversed() const override;
private:
Color oldvalue;
Color newvalue;
};
}
}
#endif // COLORDIFF_H

View file

@ -0,0 +1,74 @@
#include "ColorNode.h"
#include <cassert>
#include <sstream>
#include "ColorDiff.h"
#include "Logs.h"
// TODO Could be made into a template
ColorNode::ColorNode(DefinitionNode *parent, const string &name, const Color &value)
: DefinitionNode(parent, name, "color"), value(value) {
}
string ColorNode::toString(int indent) const {
ostringstream stream;
stream << DefinitionNode::toString(indent) << " " << value.r << "," << value.g << "," << value.b << "," << value.a;
return stream.str();
}
void ColorNode::save(PackStream *stream) const {
value.save(stream);
}
void ColorNode::load(PackStream *stream) {
value.load(stream);
}
void ColorNode::copy(DefinitionNode *destination) const {
if (auto tdest = dynamic_cast<ColorNode *>(destination)) {
tdest->value = value;
} else {
Logs::error("Definition") << "Can't copy from " << getTypeName() << " to " << destination->getTypeName()
<< endl;
}
}
void ColorNode::setValue(const Color &value) {
addDiff(produceDiff(value));
}
const ColorDiff *ColorNode::produceDiff(const Color &value) const {
return new ColorDiff(this, this->value, value);
}
void ColorNode::generateInitDiffs(vector<const DefinitionDiff *> *diffs) const {
diffs->push_back(produceDiff(value));
}
bool ColorNode::applyDiff(const DefinitionDiff *diff, bool backward) {
if (!DefinitionNode::applyDiff(diff, backward)) {
return false;
}
assert(diff->getTypeName() == "color");
auto color_diff = dynamic_cast<const ColorDiff *>(diff);
if (color_diff) {
Color previous = backward ? color_diff->getNewValue() : color_diff->getOldValue();
Color next = backward ? color_diff->getOldValue() : color_diff->getNewValue();
if (value == previous) {
value = next;
return true;
} else {
Logs::error("Definition") << "Can't apply color diff" << endl;
return false;
}
} else {
Logs::error("Could not cast DefinitionDiff to ColorDiff");
return false;
}
}

View file

@ -0,0 +1,44 @@
#ifndef COLORNODE_H
#define COLORNODE_H
#include "definition_global.h"
#include "DefinitionNode.h"
#include "Color.h"
namespace paysages {
namespace definition {
/**
* Node with a single color value, for the definition tree.
*/
class DEFINITIONSHARED_EXPORT ColorNode : public DefinitionNode {
public:
ColorNode(DefinitionNode *parent, const string &name, const Color &value = COLOR_TRANSPARENT);
inline const Color &getValue() const {
return value;
}
virtual string toString(int indent) const override;
virtual void save(PackStream *stream) const override;
virtual void load(PackStream *stream) override;
virtual void copy(DefinitionNode *destination) const override;
/**
* Change the color value stored.
*
* The DiffManager is used as intermediary, so that the change may not happen immediately.
*/
void setValue(const Color &value);
const ColorDiff *produceDiff(const Color &value) const;
virtual void generateInitDiffs(vector<const DefinitionDiff *> *diffs) const override;
virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false) override;
private:
Color value;
};
}
}
#endif // COLORNODE_H

View file

@ -249,6 +249,7 @@ void DefinitionNode::addDiff(const DefinitionDiff *diff) {
if (root && root->diffs) { if (root && root->diffs) {
root->diffs->addDiff(this, diff); root->diffs->addDiff(this, diff);
} else { } else {
// TODO Apply diff ?
delete diff; delete diff;
} }
} }

View file

@ -27,8 +27,8 @@ void FloatNode::load(PackStream *stream) {
} }
void FloatNode::copy(DefinitionNode *destination) const { void FloatNode::copy(DefinitionNode *destination) const {
if (destination->getTypeName() == getTypeName()) { if (auto tdest = dynamic_cast<FloatNode *>(destination)) {
((FloatNode *)destination)->value = value; tdest->value = value;
} else { } else {
Logs::error("Definition") << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() Logs::error("Definition") << "Can't copy from " << getTypeName() << " to " << destination->getTypeName()
<< endl; << endl;
@ -53,17 +53,22 @@ bool FloatNode::applyDiff(const DefinitionDiff *diff, bool backward) {
} }
assert(diff->getTypeName() == "float"); assert(diff->getTypeName() == "float");
const FloatDiff *float_diff = (const FloatDiff *)diff; auto float_diff = dynamic_cast<const FloatDiff *>(diff);
double previous = backward ? float_diff->getNewValue() : float_diff->getOldValue(); if (float_diff) {
double next = backward ? float_diff->getOldValue() : float_diff->getNewValue(); double previous = backward ? float_diff->getNewValue() : float_diff->getOldValue();
double next = backward ? float_diff->getOldValue() : float_diff->getNewValue();
if (value == previous) { if (value == previous) {
value = next; value = next;
return true; return true;
} else {
Logs::error("Definition") << "Can't apply float diff " << previous << " => " << next << " to " << getName()
<< endl;
return false;
}
} else { } else {
Logs::error("Definition") << "Can't apply float diff " << previous << " => " << next << " to " << getName() Logs::error("Could not cast DefinitionDiff to IntDiff");
<< endl;
return false; return false;
} }
} }

View file

@ -31,7 +31,7 @@ class DEFINITIONSHARED_EXPORT FloatNode : public DefinitionNode {
*/ */
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(vector<const DefinitionDiff *> *diffs) const; virtual void generateInitDiffs(vector<const DefinitionDiff *> *diffs) const override;
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);

View file

@ -27,8 +27,8 @@ void IntNode::load(PackStream *stream) {
} }
void IntNode::copy(DefinitionNode *destination) const { void IntNode::copy(DefinitionNode *destination) const {
if (destination->getTypeName() == getTypeName()) { if (auto tdest = dynamic_cast<IntNode *>(destination)) {
((IntNode *)destination)->value = value; tdest->value = value;
} else { } else {
Logs::error("Definition") << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() Logs::error("Definition") << "Can't copy from " << getTypeName() << " to " << destination->getTypeName()
<< endl; << endl;
@ -53,17 +53,22 @@ bool IntNode::applyDiff(const DefinitionDiff *diff, bool backward) {
} }
assert(diff->getTypeName() == "int"); assert(diff->getTypeName() == "int");
const IntDiff *int_diff = (const IntDiff *)diff; auto int_diff = dynamic_cast<const IntDiff *>(diff);
double previous = backward ? int_diff->getNewValue() : int_diff->getOldValue(); if (int_diff) {
double next = backward ? int_diff->getOldValue() : int_diff->getNewValue(); int previous = backward ? int_diff->getNewValue() : int_diff->getOldValue();
int next = backward ? int_diff->getOldValue() : int_diff->getNewValue();
if (value == previous) { if (value == previous) {
value = next; value = next;
return true; return true;
} else {
Logs::error("Definition") << "Can't apply int diff " << previous << " => " << next << " to " << getName()
<< endl;
return false;
}
} else { } else {
Logs::error("Definition") << "Can't apply int diff " << previous << " => " << next << " to " << getName() Logs::error("Could not cast DefinitionDiff to IntDiff");
<< endl;
return false; return false;
} }
} }

View file

@ -31,7 +31,7 @@ class DEFINITIONSHARED_EXPORT IntNode : public DefinitionNode {
*/ */
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(vector<const DefinitionDiff *> *diffs) const; virtual void generateInitDiffs(vector<const DefinitionDiff *> *diffs) const override;
virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false) override; virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false) override;
private: private:

View file

@ -2,19 +2,19 @@
#include "PackStream.h" #include "PackStream.h"
#include "NoiseState.h" #include "NoiseState.h"
#include "Color.h"
#include "SurfaceMaterial.h" #include "SurfaceMaterial.h"
#include "IntNode.h" #include "IntNode.h"
#include "FloatNode.h" #include "FloatNode.h"
#include "ColorNode.h"
WaterDefinition::WaterDefinition(DefinitionNode *parent) : DefinitionNode(parent, "water", "water") { WaterDefinition::WaterDefinition(DefinitionNode *parent) : DefinitionNode(parent, "water", "water") {
model = new IntNode(this, "model", -1); model = new IntNode(this, "model", -1);
reflection = new FloatNode(this, "reflection"); reflection = new FloatNode(this, "reflection");
xoffset = new FloatNode(this, "xoffset"); xoffset = new FloatNode(this, "xoffset");
zoffset = new FloatNode(this, "zoffset"); zoffset = new FloatNode(this, "zoffset");
depth_color = new ColorNode(this, "depth_color");
material = new SurfaceMaterial; material = new SurfaceMaterial;
depth_color = new Color;
foam_material = new SurfaceMaterial; foam_material = new SurfaceMaterial;
noise_state = new NoiseState(); noise_state = new NoiseState();
@ -32,7 +32,6 @@ WaterDefinition::WaterDefinition(DefinitionNode *parent) : DefinitionNode(parent
WaterDefinition::~WaterDefinition() { WaterDefinition::~WaterDefinition() {
delete material; delete material;
delete depth_color;
delete foam_material; delete foam_material;
delete noise_state; delete noise_state;
} }
@ -41,7 +40,6 @@ void WaterDefinition::save(PackStream *stream) const {
DefinitionNode::save(stream); DefinitionNode::save(stream);
material->save(stream); material->save(stream);
depth_color->save(stream);
stream->write(&transparency_depth); stream->write(&transparency_depth);
stream->write(&transparency); stream->write(&transparency);
stream->write(&lighting_depth); stream->write(&lighting_depth);
@ -61,7 +59,6 @@ void WaterDefinition::load(PackStream *stream) {
DefinitionNode::load(stream); DefinitionNode::load(stream);
material->load(stream); material->load(stream);
depth_color->load(stream);
stream->read(&transparency_depth); stream->read(&transparency_depth);
stream->read(&transparency); stream->read(&transparency);
stream->read(&lighting_depth); stream->read(&lighting_depth);
@ -84,7 +81,6 @@ void WaterDefinition::copy(DefinitionNode *_destination) const {
WaterDefinition *destination = (WaterDefinition *)_destination; WaterDefinition *destination = (WaterDefinition *)_destination;
*destination->material = *material; *destination->material = *material;
*destination->depth_color = *depth_color;
destination->transparency_depth = transparency_depth; destination->transparency_depth = transparency_depth;
destination->transparency = transparency; destination->transparency = transparency;
destination->lighting_depth = lighting_depth; destination->lighting_depth = lighting_depth;
@ -100,7 +96,6 @@ void WaterDefinition::copy(DefinitionNode *_destination) const {
void WaterDefinition::validate() { void WaterDefinition::validate() {
DefinitionNode::validate(); DefinitionNode::validate();
depth_color->a = 1.0;
material->base->a = 1.0; material->base->a = 1.0;
material->reflection = 1.0; material->reflection = 1.0;
material->shininess = 16.0; material->shininess = 16.0;
@ -116,17 +111,13 @@ void WaterDefinition::validate() {
void WaterDefinition::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) { void WaterDefinition::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) {
if (node == model) { if (node == model) {
noise_state->randomizeOffsets();
switch (model->getValue()) { switch (model->getValue()) {
case 1: case 1:
transparency = 0.3; transparency = 0.3;
reflection->setValue(0.07); reflection->setValue(0.07);
transparency_depth = 3.0; transparency_depth = 3.0;
material->setColor(0.05, 0.18, 0.2, 1.0); material->setColor(0.05, 0.18, 0.2, 1.0);
depth_color->r = 0.0; depth_color->setValue(Color(0.0, 0.18, 0.15));
depth_color->g = 0.18;
depth_color->b = 0.15;
lighting_depth = 4.0; lighting_depth = 4.0;
scaling = 1.5; scaling = 1.5;
waves_height = 1.0; waves_height = 1.0;
@ -140,9 +131,7 @@ void WaterDefinition::nodeChanged(const DefinitionNode *node, const DefinitionDi
reflection->setValue(0.2); reflection->setValue(0.2);
transparency_depth = 4.0; transparency_depth = 4.0;
material->setColor(0.08, 0.15, 0.2, 1.0); material->setColor(0.08, 0.15, 0.2, 1.0);
depth_color->r = 0.0; depth_color->setValue(Color(0.0, 0.1, 0.1));
depth_color->g = 0.1;
depth_color->b = 0.1;
lighting_depth = 6.0; lighting_depth = 6.0;
scaling = 1.0; scaling = 1.0;
waves_height = 0.8; waves_height = 0.8;
@ -155,6 +144,8 @@ void WaterDefinition::nodeChanged(const DefinitionNode *node, const DefinitionDi
} }
void WaterDefinition::applyPreset(WaterPreset preset, RandomGenerator &random) { void WaterDefinition::applyPreset(WaterPreset preset, RandomGenerator &random) {
noise_state->randomizeOffsets(random);
if (preset == WATER_PRESET_LAKE) { if (preset == WATER_PRESET_LAKE) {
model->setValue(0); model->setValue(0);
} else if (preset == WATER_PRESET_SEA) { } else if (preset == WATER_PRESET_SEA) {

View file

@ -32,6 +32,9 @@ class DEFINITIONSHARED_EXPORT WaterDefinition : public DefinitionNode, public De
inline FloatNode *propZOffset() const { inline FloatNode *propZOffset() const {
return zoffset; return zoffset;
} }
inline ColorNode *propDepthColor() const {
return depth_color;
}
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff); virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff);
@ -41,7 +44,6 @@ class DEFINITIONSHARED_EXPORT WaterDefinition : public DefinitionNode, public De
public: public:
double transparency; double transparency;
SurfaceMaterial *material; SurfaceMaterial *material;
Color *depth_color;
double transparency_depth; double transparency_depth;
double lighting_depth; double lighting_depth;
@ -60,6 +62,7 @@ class DEFINITIONSHARED_EXPORT WaterDefinition : public DefinitionNode, public De
FloatNode *reflection; FloatNode *reflection;
FloatNode *xoffset; FloatNode *xoffset;
FloatNode *zoffset; FloatNode *zoffset;
ColorNode *depth_color;
}; };
} }
} }

View file

@ -18,6 +18,8 @@ class FloatDiff;
class IntNode; class IntNode;
class IntDiff; class IntDiff;
class NoiseNode; class NoiseNode;
class ColorNode;
class ColorDiff;
class DiffManager; class DiffManager;
class DefinitionWatcher; class DefinitionWatcher;
class Scenery; class Scenery;

View file

@ -10,6 +10,7 @@
#include "SurfaceMaterial.h" #include "SurfaceMaterial.h"
#include "NoiseFunctionSimplex.h" #include "NoiseFunctionSimplex.h"
#include "FloatNode.h" #include "FloatNode.h"
#include "ColorNode.h"
#include "RayCastingResult.h" #include "RayCastingResult.h"
WaterRenderer::WaterRenderer(SoftwareRenderer *parent) : parent(parent) { WaterRenderer::WaterRenderer(SoftwareRenderer *parent) : parent(parent) {
@ -178,7 +179,7 @@ WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z) {
if (definition->transparency == 0.0) { if (definition->transparency == 0.0) {
result.refracted = COLOR_BLACK; result.refracted = COLOR_BLACK;
} else { } else {
Color depth_color = *definition->depth_color; Color depth_color = definition->propDepthColor()->getValue();
refracted = parent->rayWalking(location, _refractRay(look_direction, normal), 1, 0, 1, 1); refracted = parent->rayWalking(location, _refractRay(look_direction, normal), 1, 0, 1, 1);
depth = location.sub(refracted.hit_location).getNorm(); depth = location.sub(refracted.hit_location).getNorm();
depth_color.limitPower(refracted.hit_color.getPower()); depth_color.limitPower(refracted.hit_color.getPower());

View file

@ -0,0 +1,108 @@
#include "BaseTestCase.h"
#include "ColorNode.h"
#include "ColorDiff.h"
#include "IntDiff.h"
#include "PackStream.h"
TEST(ColorNode, toString) {
ColorNode test(NULL, "test", Color(0.1, 0.2, 0.3, 0.4));
EXPECT_EQ("test 0.1,0.2,0.3,0.4", test.toString(0));
EXPECT_EQ(" test 0.1,0.2,0.3,0.4", test.toString(2));
}
TEST(ColorNode, saveLoadAndSkip) {
DefinitionNode root1(NULL, "root");
ColorNode testa1(&root1, "testa", COLOR_RED);
ColorNode testb1(&root1, "testb", COLOR_GREEN);
PackStream stream1;
root1.save(&stream1);
DefinitionNode root2(NULL, "root");
ColorNode testb2(&root2, "testb");
PackStream stream2(&stream1);
root2.load(&stream2);
EXPECT_EQ(COLOR_GREEN, testb2.getValue());
}
TEST(ColorNode, copy) {
ColorNode base(NULL, "test", COLOR_BLUE);
ColorNode other(NULL, "test", COLOR_RED);
DefinitionNode badother(NULL, "test");
base.copy(&other);
EXPECT_EQ(COLOR_BLUE, base.getValue());
EXPECT_EQ(COLOR_BLUE, other.getValue());
badother.copy(&base);
EXPECT_EQ(COLOR_BLUE, base.getValue());
base.copy(&badother);
// can't check anything, just useful in valgrind
}
TEST(ColorNode, produceDiff) {
ColorNode node(NULL, "test", COLOR_BLUE);
const ColorDiff *diff = node.produceDiff(COLOR_RED);
EXPECT_EQ("color", diff->getTypeName());
EXPECT_EQ(COLOR_BLUE, diff->getOldValue());
EXPECT_EQ(COLOR_RED, diff->getNewValue());
bool result = node.applyDiff(diff);
EXPECT_TRUE(result);
EXPECT_EQ(COLOR_RED, node.getValue());
delete diff;
}
TEST(ColorNode, applyDiff) {
ColorNode node(NULL, "test", COLOR_BLUE);
ColorDiff diff(&node, COLOR_BLUE, COLOR_RED);
DefinitionNode onode(NULL, "test", "badtype");
IntDiff odiff(&onode, 1, 2);
bool result;
EXPECT_EQ(COLOR_BLUE, node.getValue());
// apply
result = node.applyDiff(&diff);
EXPECT_TRUE(result);
EXPECT_EQ(COLOR_RED, node.getValue());
// can't apply twice
result = node.applyDiff(&diff);
EXPECT_FALSE(result);
EXPECT_EQ(COLOR_RED, node.getValue());
// reverse
result = node.applyDiff(&diff, true);
EXPECT_TRUE(result);
EXPECT_EQ(COLOR_BLUE, node.getValue());
// can't reverse twice
result = node.applyDiff(&diff, true);
EXPECT_FALSE(result);
EXPECT_EQ(COLOR_BLUE, node.getValue());
// bad type
result = node.applyDiff(&odiff);
EXPECT_FALSE(result);
EXPECT_EQ(COLOR_BLUE, node.getValue());
// apply again
result = node.applyDiff(&diff);
EXPECT_TRUE(result);
EXPECT_EQ(COLOR_RED, node.getValue());
}