Added TimeManager with basic wind control for videos

This commit is contained in:
Michaël Lemaire 2015-10-15 17:52:03 +02:00
parent c62cf3a0a4
commit cd144b886c
16 changed files with 178 additions and 27 deletions

1
TODO
View file

@ -6,6 +6,7 @@ Technlology Preview 2 :
- Refactor medium traversal to unify clouds, atmosphere and god rays. - Refactor medium traversal to unify clouds, atmosphere and god rays.
- Fix potential holes in land rendering (OpenGL and software). - Fix potential holes in land rendering (OpenGL and software).
- Fix sun size not being consistent between opengl and software - Fix sun size not being consistent between opengl and software
- Fix CanvasPortion saves colliding on disk when running several instances
Technology Preview 3 : Technology Preview 3 :
- Alter aerial perspective using estimation of the amount of light left after cloud layers traversal. - Alter aerial perspective using estimation of the amount of light left after cloud layers traversal.

View file

@ -4,6 +4,7 @@
#include "NoiseGenerator.h" #include "NoiseGenerator.h"
#include "SurfaceMaterial.h" #include "SurfaceMaterial.h"
#include "PackStream.h" #include "PackStream.h"
#include "FloatNode.h"
CloudLayerDefinition::CloudLayerDefinition(DefinitionNode* parent): CloudLayerDefinition::CloudLayerDefinition(DefinitionNode* parent):
DefinitionNode(parent, "layer", "cloudlayer") DefinitionNode(parent, "layer", "cloudlayer")
@ -12,6 +13,9 @@ CloudLayerDefinition::CloudLayerDefinition(DefinitionNode* parent):
altitude = 0.5; altitude = 0.5;
scaling = 0.5; scaling = 0.5;
coverage = 0.5; coverage = 0.5;
xoffset = new FloatNode(this, "xoffset");
zoffset = new FloatNode(this, "zoffset");
} }
CloudLayerDefinition::~CloudLayerDefinition() CloudLayerDefinition::~CloudLayerDefinition()
@ -79,6 +83,8 @@ void CloudLayerDefinition::copy(DefinitionNode* _destination) const
void CloudLayerDefinition::validate() void CloudLayerDefinition::validate()
{ {
DefinitionNode::validate();
if (scaling < 0.1) if (scaling < 0.1)
{ {
scaling = 0.1; scaling = 0.1;

View file

@ -17,6 +17,8 @@ public:
virtual ~CloudLayerDefinition(); virtual ~CloudLayerDefinition();
inline const NoiseState &getNoiseState() const {return noise_state;} inline const NoiseState &getNoiseState() const {return noise_state;}
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;
@ -48,6 +50,10 @@ public:
double altitude; double altitude;
double scaling; double scaling;
double coverage; double coverage;
private:
FloatNode *xoffset;
FloatNode *zoffset;
}; };
} }

View file

@ -81,3 +81,8 @@ bool FloatNode::applyDiff(const DefinitionDiff *diff, bool backward)
return false; return false;
} }
} }
void FloatNode::addValue(double added)
{
setValue(value + added);
}

View file

@ -32,6 +32,8 @@ public:
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);
private: private:
double value; double value;
}; };

View file

@ -0,0 +1,42 @@
#include "TimeManager.h"
#include "Scenery.h"
#include "AtmosphereDefinition.h"
#include "FloatNode.h"
#include "CloudsDefinition.h"
#include "CloudLayerDefinition.h"
#include "WaterDefinition.h"
TimeManager::TimeManager()
{
wind_x = 0.0;
wind_z = 0.0;
}
void TimeManager::moveForward(Scenery *scenery, double amount)
{
// Move the sun
scenery->getAtmosphere()->setDayTime(scenery->getAtmosphere()->propDayTime()->getValue() + amount);
// Move the clouds
int n = scenery->getClouds()->count();
for (int i = 0; i < n; i++)
{
CloudLayerDefinition *cloud = scenery->getClouds()->getCloudLayer(i);
cloud->propXOffset()->addValue(-wind_x * amount * 100.0);
cloud->propZOffset()->addValue(-wind_z * amount * 100.0);
// TODO Alter noise offsets
}
// Move the water
WaterDefinition *water = scenery->getWater();
water->propXOffset()->addValue(-wind_x * amount * 10.0);
water->propZOffset()->addValue(-wind_z * amount * 10.0);
// TODO Alter noise offsets
}
void TimeManager::setWind(double wind_x, double wind_z)
{
this->wind_x = wind_x;
this->wind_z = wind_z;
}

View file

@ -0,0 +1,37 @@
#ifndef TIMEMANAGER_H
#define TIMEMANAGER_H
#include "definition_global.h"
namespace paysages {
namespace definition {
/**
* Time manager, handling the inexorable passing of time.
*/
class DEFINITIONSHARED_EXPORT TimeManager
{
public:
TimeManager();
/**
* Alter a scenery to simulate the passing of *amount* of time.
*
* A 1.0 amount is a full day.
*/
void moveForward(Scenery *scenery, double amount);
/**
* Set the wind factor in each direction.
*/
void setWind(double wind_x, double wind_z);
private:
double wind_x;
double wind_z;
};
}
}
#endif // TIMEMANAGER_H

View file

@ -12,6 +12,8 @@ WaterDefinition::WaterDefinition(DefinitionNode* parent):
{ {
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");
zoffset = new FloatNode(this, "zoffset");
material = new SurfaceMaterial; material = new SurfaceMaterial;
depth_color = new Color; depth_color = new Color;

View file

@ -23,6 +23,8 @@ public:
inline IntNode *propModel() const {return model;} inline IntNode *propModel() const {return model;}
inline FloatNode *propReflection() const {return reflection;} inline FloatNode *propReflection() const {return reflection;}
inline FloatNode *propXOffset() const {return xoffset;}
inline FloatNode *propZOffset() const {return zoffset;}
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff); virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff);
@ -53,6 +55,8 @@ public:
private: private:
IntNode *model; IntNode *model;
FloatNode *reflection; FloatNode *reflection;
FloatNode *xoffset;
FloatNode *zoffset;
}; };
} }

View file

@ -38,7 +38,8 @@ SOURCES += \
DefinitionWatcher.cpp \ DefinitionWatcher.cpp \
IntNode.cpp \ IntNode.cpp \
IntDiff.cpp \ IntDiff.cpp \
GodRaysDefinition.cpp GodRaysDefinition.cpp \
TimeManager.cpp
HEADERS +=\ HEADERS +=\
definition_global.h \ definition_global.h \
@ -66,7 +67,8 @@ HEADERS +=\
DefinitionWatcher.h \ DefinitionWatcher.h \
IntNode.h \ IntNode.h \
IntDiff.h \ IntDiff.h \
GodRaysDefinition.h GodRaysDefinition.h \
TimeManager.h
unix:!symbian { unix:!symbian {
maemo5 { maemo5 {

View file

@ -43,6 +43,7 @@ namespace definition {
class PaintedGridBrushAddNoise; class PaintedGridBrushAddNoise;
class PaintedGridBrushReset; class PaintedGridBrushReset;
class PaintedGridBrushFlatten; class PaintedGridBrushFlatten;
class TimeManager;
} }
} }
using namespace paysages::definition; using namespace paysages::definition;

View file

@ -3,6 +3,7 @@
#include "Scenery.h" #include "Scenery.h"
#include "AtmosphereDefinition.h" #include "AtmosphereDefinition.h"
#include "CameraDefinition.h" #include "CameraDefinition.h"
#include "TimeManager.h"
#include <cstring> #include <cstring>
@ -21,6 +22,8 @@ static void displayHelp()
printf(" -rh x Render height (int)\n"); printf(" -rh x Render height (int)\n");
printf(" -rq x Render quality (int, 1 to 10)\n"); printf(" -rq x Render quality (int, 1 to 10)\n");
printf(" -ra x Render anti-aliasing (int, 1 to 4)\n"); printf(" -ra x Render anti-aliasing (int, 1 to 4)\n");
printf(" -wx x Wind power in X direction (double)\n");
printf(" -wz z Wind power in Z direction (double)\n");
printf(" -di x Day start time (double, 0.0 to 1.0)\n"); printf(" -di x Day start time (double, 0.0 to 1.0)\n");
printf(" -ds x Day step time (double)\n"); printf(" -ds x Day step time (double)\n");
printf(" -cx x Camera X step (double)\n"); printf(" -cx x Camera X step (double)\n");
@ -40,6 +43,8 @@ int main(int argc, char** argv)
double conf_camera_step_x = 0.0; double conf_camera_step_x = 0.0;
double conf_camera_step_y = 0.0; double conf_camera_step_y = 0.0;
double conf_camera_step_z = 0.0; double conf_camera_step_z = 0.0;
double conf_wind_x = 0.0;
double conf_wind_z = 0.0;
int outputcount; int outputcount;
char outputpath[500]; char outputpath[500];
@ -107,6 +112,20 @@ int main(int argc, char** argv)
conf_render_params.antialias = atoi(*(++argv)); conf_render_params.antialias = atoi(*(++argv));
} }
} }
else if (strcmp(*argv, "-wx") == 0 || strcmp(*argv, "--windx") == 0)
{
if (argc--)
{
conf_wind_x = atof(*(++argv));
}
}
else if (strcmp(*argv, "-wz") == 0 || strcmp(*argv, "--windz") == 0)
{
if (argc--)
{
conf_wind_z = atof(*(++argv));
}
}
else if (strcmp(*argv, "-di") == 0 || strcmp(*argv, "--daystart") == 0) else if (strcmp(*argv, "-di") == 0 || strcmp(*argv, "--daystart") == 0)
{ {
if (argc--) if (argc--)
@ -158,15 +177,15 @@ int main(int argc, char** argv)
scenery->autoPreset(); scenery->autoPreset();
} }
TimeManager time;
time.setWind(conf_wind_x, conf_wind_z);
if (conf_daytime_start >= 0.0)
{
scenery->getAtmosphere()->setDayTime(conf_daytime_start);
}
for (outputcount = 0; outputcount < conf_first_picture + conf_nb_pictures; outputcount++) for (outputcount = 0; outputcount < conf_first_picture + conf_nb_pictures; outputcount++)
{ {
if (conf_daytime_start >= 0.0)
{
AtmosphereDefinition* atmo = scenery->getAtmosphere();
atmo->setDayTime(conf_daytime_start);
atmo->validate();
}
CameraDefinition* camera = scenery->getCamera(); CameraDefinition* camera = scenery->getCamera();
Vector3 step = {conf_camera_step_x, conf_camera_step_y, conf_camera_step_z}; Vector3 step = {conf_camera_step_x, conf_camera_step_y, conf_camera_step_z};
camera->setLocation(camera->getLocation().add(step)); camera->setLocation(camera->getLocation().add(step));
@ -182,7 +201,7 @@ int main(int argc, char** argv)
delete renderer; delete renderer;
conf_daytime_start += conf_daytime_step; time.moveForward(scenery, conf_daytime_step);
} }
printf("Cleaning up ...\n"); printf("Cleaning up ...\n");

View file

@ -203,7 +203,6 @@ static void testNearFrustum()
scenery.autoPreset(3); scenery.autoPreset(3);
scenery.getCamera()->setLocation(Vector3(0.0, 0.0, 0.0)); scenery.getCamera()->setLocation(Vector3(0.0, 0.0, 0.0));
scenery.getCamera()->setTarget(Vector3(1.0, 0.0, 1.0)); scenery.getCamera()->setTarget(Vector3(1.0, 0.0, 1.0));
scenery.keepCameraAboveGround(scenery.getCamera());
SoftwareCanvasRenderer renderer(&scenery); SoftwareCanvasRenderer renderer(&scenery);
renderer.setSize(400, 300); renderer.setSize(400, 300);
@ -231,6 +230,27 @@ static void testCloudsNearGround()
startTestRender(&renderer, "clouds_near_ground", 2); startTestRender(&renderer, "clouds_near_ground", 2);
} }
static void testSunNearHorizon()
{
Scenery scenery;
scenery.autoPreset(28);
scenery.getCamera()->setLocation(VECTOR_ZERO);
scenery.getCamera()->setTarget(VECTOR_EAST);
scenery.getClouds()->clear();
scenery.getTextures()->applyPreset(TexturesDefinition::TEXTURES_PRESET_CANYON);
scenery.getTerrain()->propWaterHeight()->setValue(-1.0);
SoftwareCanvasRenderer renderer(&scenery);
renderer.setSize(400, 300);
renderer.setQuality(0.3);
for (int i = 0; i <= 20; i++)
{
scenery.getAtmosphere()->propDayTime()->setValue(0.24 + 0.001 * (double)i);
startTestRender(&renderer, "sun_near_horizon", i);
}
}
void runTestSuite() void runTestSuite()
{ {
testGroundShadowQuality(); testGroundShadowQuality();
@ -239,4 +259,5 @@ void runTestSuite()
testGodRays(); testGodRays();
testNearFrustum(); testNearFrustum();
testCloudsNearGround(); testCloudsNearGround();
testSunNearHorizon();
} }

View file

@ -10,6 +10,7 @@
#include "clouds/BaseCloudsModel.h" #include "clouds/BaseCloudsModel.h"
#include "SurfaceMaterial.h" #include "SurfaceMaterial.h"
#include "Logs.h" #include "Logs.h"
#include "FloatNode.h"
#include <cassert> #include <cassert>
@ -25,7 +26,7 @@ CloudBasicLayerRenderer::CloudBasicLayerRenderer(SoftwareRenderer* parent):
{ {
} }
static inline double _getDistanceToBorder(BaseCloudsModel* model, Vector3 position) static inline double _getDistanceToBorder(BaseCloudsModel* model, const Vector3 &position)
{ {
return model->getDensity(position); return model->getDensity(position);
} }
@ -54,7 +55,7 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
double step_length, segment_length; double step_length, segment_length;
double min_step, max_step; double min_step, max_step;
double noise_distance; double noise_distance;
Vector3 walker, step, segment_start; Vector3 walker, step, segment_start, offset;
double render_precision; double render_precision;
if (max_segments <= 0) if (max_segments <= 0)
@ -80,7 +81,8 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
current_inside_length = 0.0; current_inside_length = 0.0;
segment_length = 0.0; segment_length = 0.0;
walker = start; walker = start;
noise_distance = _getDistanceToBorder(model, start) * render_precision; offset = Vector3(model->getLayer()->propXOffset()->getValue(), 0.0, model->getLayer()->propZOffset()->getValue());
noise_distance = _getDistanceToBorder(model, start.add(offset)) * render_precision;
inside = 0; inside = 0;
step = direction.scale(render_precision); step = direction.scale(render_precision);
@ -88,7 +90,7 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
{ {
walker = walker.add(step); walker = walker.add(step);
step_length = step.getNorm(); step_length = step.getNorm();
noise_distance = _getDistanceToBorder(model, walker) * render_precision; noise_distance = _getDistanceToBorder(model, walker.add(offset)) * render_precision;
current_total_length += step_length; current_total_length += step_length;
if (noise_distance > 0.0) if (noise_distance > 0.0)

View file

@ -69,6 +69,7 @@ SoftwareRenderer::~SoftwareRenderer()
void SoftwareRenderer::prepare() void SoftwareRenderer::prepare()
{ {
scenery->validate(); scenery->validate();
scenery->getCamera()->copy(render_camera);
// Prepare sub renderers // Prepare sub renderers
// TODO Don't recreate the renderer each time, only when it changes // TODO Don't recreate the renderer each time, only when it changes

View file

@ -29,12 +29,12 @@ void WaterRenderer::update()
noise->setStep(0.3); noise->setStep(0.3);
} }
static inline double _getHeight(FractalNoise* noise, double x, double z) static inline double _getHeight(WaterDefinition* definition, FractalNoise* noise, double x, double z)
{ {
return noise->get2d(0.00001, x, z); return noise->get2d(0.00001, x + definition->propXOffset()->getValue(), z + definition->propZOffset()->getValue());
} }
static inline Vector3 _getNormal(FractalNoise* noise, Vector3 base, double detail) static inline Vector3 _getNormal(WaterDefinition* definition, FractalNoise* noise, Vector3 base, double detail)
{ {
Vector3 back, right; Vector3 back, right;
double x, z; double x, z;
@ -43,12 +43,12 @@ static inline Vector3 _getNormal(FractalNoise* noise, Vector3 base, double detai
z = base.z; z = base.z;
back.x = x; back.x = x;
back.y = _getHeight(noise, x, z + detail); back.y = _getHeight(definition, noise, x, z + detail);
back.z = z + detail; back.z = z + detail;
back = back.sub(base); back = back.sub(base);
right.x = x + detail; right.x = x + detail;
right.y = _getHeight(noise, x + detail, z); right.y = _getHeight(definition, noise, x + detail, z);
right.z = z; right.z = z;
right = right.sub(base); right = right.sub(base);
@ -89,26 +89,26 @@ static inline Color _getFoamMask(SoftwareRenderer* renderer, WaterDefinition* de
foam_factor = 0.0; foam_factor = 0.0;
location.x += location_offset; location.x += location_offset;
normal_diff = 1.0 - normal.dotProduct(_getNormal(noise, location, detail)); normal_diff = 1.0 - normal.dotProduct(_getNormal(definition, noise, location, detail));
if (normal_diff > foam_factor) if (normal_diff > foam_factor)
{ {
foam_factor = normal_diff; foam_factor = normal_diff;
} }
location.x -= location_offset * 2.0; location.x -= location_offset * 2.0;
normal_diff = 1.0 - normal.dotProduct(_getNormal(noise, location, detail)); normal_diff = 1.0 - normal.dotProduct(_getNormal(definition, noise, location, detail));
if (normal_diff > foam_factor) if (normal_diff > foam_factor)
{ {
foam_factor = normal_diff; foam_factor = normal_diff;
} }
location.x += location_offset; location.x += location_offset;
location.z -= location_offset; location.z -= location_offset;
normal_diff = 1.0 - normal.dotProduct(_getNormal(noise, location, detail)); normal_diff = 1.0 - normal.dotProduct(_getNormal(definition, noise, location, detail));
if (normal_diff > foam_factor) if (normal_diff > foam_factor)
{ {
foam_factor = normal_diff; foam_factor = normal_diff;
} }
location.z += location_offset * 2.0; location.z += location_offset * 2.0;
normal_diff = 1.0 - normal.dotProduct(_getNormal(noise, location, detail)); normal_diff = 1.0 - normal.dotProduct(_getNormal(definition, noise, location, detail));
if (normal_diff > foam_factor) if (normal_diff > foam_factor)
{ {
foam_factor = normal_diff; foam_factor = normal_diff;
@ -162,7 +162,7 @@ HeightInfo WaterRenderer::getHeightInfo()
double WaterRenderer::getHeight(double x, double z) double WaterRenderer::getHeight(double x, double z)
{ {
return _getHeight(noise, x, z); return _getHeight(parent->getScenery()->getWater(), noise, x, z);
} }
WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z) WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z)
@ -176,7 +176,7 @@ WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z)
double reflection = definition->propReflection()->getValue(); double reflection = definition->propReflection()->getValue();
location.x = x; location.x = x;
location.y = _getHeight(noise, x, z); location.y = _getHeight(definition, noise, x, z);
location.z = z; location.z = z;
result.location = location; result.location = location;
@ -186,7 +186,7 @@ WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z)
detail = 0.00001; detail = 0.00001;
} }
normal = _getNormal(noise, location, detail); normal = _getNormal(definition, noise, location, detail);
look_direction = location.sub(parent->getCameraLocation(location)).normalize(); look_direction = location.sub(parent->getCameraLocation(location)).normalize();
/* Reflection */ /* Reflection */