Added NoiseState offsets to FractalNoise

This commit is contained in:
Michaël Lemaire 2014-01-01 18:21:34 +01:00
parent 22cf9fde51
commit 67ae34ddbd
5 changed files with 112 additions and 5 deletions

View file

@ -32,18 +32,33 @@ void FractalNoise::setRidge(double ridge_factor)
this->ridge = ridge_factor; this->ridge = ridge_factor;
} }
void FractalNoise::setState(const NoiseState &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 i = 0;
while (current_height >= detail) while (current_height >= detail)
{ {
result += getBase1d(x * current_scaling) * current_height; const NoiseState::NoiseOffset &offset = state.level_offsets[i];
result += getBase1d(offset.x + x * current_scaling) * current_height;
current_scaling *= step_scaling; current_scaling *= step_scaling;
current_height *= step_height; current_height *= step_height;
i++;
if (i >= state_level_count)
{
i = 0;
}
} }
return result; return result;
@ -54,13 +69,23 @@ 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 i = 0;
while (current_height >= detail) while (current_height >= detail)
{ {
result += getBase2d(x * current_scaling, y * current_scaling) * current_height; const NoiseState::NoiseOffset &offset = state.level_offsets[i];
result += getBase2d(offset.x + x * current_scaling, offset.y + y * current_scaling) * current_height;
current_scaling *= step_scaling; current_scaling *= step_scaling;
current_height *= step_height; current_height *= step_height;
i++;
if (i >= state_level_count)
{
i = 0;
}
} }
return result; return result;
@ -71,13 +96,23 @@ 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 i = 0;
while (current_height >= detail) while (current_height >= detail)
{ {
result += getBase3d(x * current_scaling, y * current_scaling, z * current_scaling) * current_height; 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;
current_scaling *= step_scaling; current_scaling *= step_scaling;
current_height *= step_height; current_height *= step_height;
i++;
if (i >= state_level_count)
{
i = 0;
}
} }
return result; return result;

View file

@ -20,6 +20,7 @@ public:
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);
double get1d(double detail, double x) const; double get1d(double detail, double x) const;
double get2d(double detail, double x, double y) const; double get2d(double detail, double x, double y) const;

View file

@ -63,3 +63,14 @@ void NoiseState::resetOffsets(double x, double y, double z)
level_offset.z = z; level_offset.z = z;
} }
} }
void NoiseState::setLevel(int level, double x, double y, double z)
{
NoiseOffset offset = {x, y, z};
level_offsets.at(level) = offset;
}
void NoiseState::setLevelCount(int level_count)
{
level_offsets.resize(level_count);
}

View file

@ -30,10 +30,14 @@ public:
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 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;
}; };
} }

View file

@ -7,6 +7,10 @@ class TestFractalNoise:public FractalNoise
public: public:
TestFractalNoise(double value=0.0):FractalNoise(), value(value) TestFractalNoise(double value=0.0):FractalNoise(), value(value)
{ {
NoiseState state;
state.resetOffsets();
setState(state);
calls = 0; calls = 0;
} }
@ -148,22 +152,74 @@ TEST(FractalNoise, StepScalingAndHeight)
EXPECT_DOUBLE_EQ(1.8 + 0.7 + 0.3, result); EXPECT_DOUBLE_EQ(1.8 + 0.7 + 0.3, result);
} }
TEST(FractalNoise, StateOffset)
{
TestFractalNoise noise(0.8);
NoiseState state;
state.resetOffsets(0.2);
noise.setState(state);
double result = noise.get1d(0.4, 1.0);
ASSERT_EQ(2, noise.calls);
EXPECT_DOUBLE_EQ(2.0 + 1.5, result);
}
TEST(FractalNoise, StateOffsetIter)
{
TestFractalNoise noise(0.8);
NoiseState state;
state.setLevel(0, 0.1, 0.1, 0.1);
state.setLevel(1, 0.6, 0.6, 0.6);
noise.setState(state);
double result = noise.get1d(0.4, 1.0);
ASSERT_EQ(2, noise.calls);
EXPECT_DOUBLE_EQ(1.9 + 1.7, result);
}
TEST(FractalNoise, StateOffsetLoop)
{
TestFractalNoise noise(0.8);
NoiseState state;
state.setLevelCount(2);
state.setLevel(0, 0.1, 0.1, 0.1);
state.setLevel(1, 0.6, 0.6, 0.6);
noise.setState(state);
double result = noise.get1d(0.2, 1.0);
ASSERT_EQ(3, noise.calls);
EXPECT_DOUBLE_EQ(1.9 + 1.7 + 1.225, result);
}
TEST(FractalNoise, Noise2d) TEST(FractalNoise, Noise2d)
{ {
TestFractalNoise noise(0.8); TestFractalNoise noise(0.8);
NoiseState state;
state.setLevelCount(2);
state.setLevel(0, 0.1, 0.2, 0.3);
state.setLevel(1, 0.6, 0.7, 0.8);
noise.setState(state);
double result = noise.get2d(0.4, 1.0, 0.5); double result = noise.get2d(0.4, 1.0, 0.5);
ASSERT_EQ(2, noise.calls); ASSERT_EQ(2, noise.calls);
EXPECT_DOUBLE_EQ(2.3 + 1.9, result); EXPECT_DOUBLE_EQ(2.6 + 2.55, result);
} }
TEST(FractalNoise, Noise3d) TEST(FractalNoise, Noise3d)
{ {
TestFractalNoise noise(0.8); TestFractalNoise noise(0.8);
NoiseState state;
state.setLevelCount(2);
state.setLevel(0, 0.1, 0.2, 0.3);
state.setLevel(1, 0.6, 0.7, 0.8);
noise.setState(state);
double result = noise.get3d(0.4, 1.0, 0.5, 0.3); double result = noise.get3d(0.4, 1.0, 0.5, 0.3);
ASSERT_EQ(2, noise.calls); ASSERT_EQ(2, noise.calls);
EXPECT_DOUBLE_EQ(2.6 + 2.2, result); EXPECT_DOUBLE_EQ(3.2 + 3.25, result);
} }