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.
- Fix potential holes in land rendering (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 :
- 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 "SurfaceMaterial.h"
#include "PackStream.h"
#include "FloatNode.h"
CloudLayerDefinition::CloudLayerDefinition(DefinitionNode* parent):
DefinitionNode(parent, "layer", "cloudlayer")
@ -12,6 +13,9 @@ CloudLayerDefinition::CloudLayerDefinition(DefinitionNode* parent):
altitude = 0.5;
scaling = 0.5;
coverage = 0.5;
xoffset = new FloatNode(this, "xoffset");
zoffset = new FloatNode(this, "zoffset");
}
CloudLayerDefinition::~CloudLayerDefinition()
@ -79,6 +83,8 @@ void CloudLayerDefinition::copy(DefinitionNode* _destination) const
void CloudLayerDefinition::validate()
{
DefinitionNode::validate();
if (scaling < 0.1)
{
scaling = 0.1;

View file

@ -17,6 +17,8 @@ public:
virtual ~CloudLayerDefinition();
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);
CloudLayerDefinition* newCopy(DefinitionNode* parent) const;
@ -48,6 +50,10 @@ public:
double altitude;
double scaling;
double coverage;
private:
FloatNode *xoffset;
FloatNode *zoffset;
};
}

View file

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

View file

@ -32,6 +32,8 @@ public:
const FloatDiff *produceDiff(double new_value) const;
void generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const;
virtual bool applyDiff(const DefinitionDiff *diff, bool backward=false) override;
void addValue(double added);
private:
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);
reflection = new FloatNode(this, "reflection");
xoffset = new FloatNode(this, "xoffset");
zoffset = new FloatNode(this, "zoffset");
material = new SurfaceMaterial;
depth_color = new Color;

View file

@ -23,6 +23,8 @@ public:
inline IntNode *propModel() const {return model;}
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);
@ -53,6 +55,8 @@ public:
private:
IntNode *model;
FloatNode *reflection;
FloatNode *xoffset;
FloatNode *zoffset;
};
}

View file

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

View file

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

View file

@ -3,6 +3,7 @@
#include "Scenery.h"
#include "AtmosphereDefinition.h"
#include "CameraDefinition.h"
#include "TimeManager.h"
#include <cstring>
@ -21,6 +22,8 @@ static void displayHelp()
printf(" -rh x Render height (int)\n");
printf(" -rq x Render quality (int, 1 to 10)\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(" -ds x Day step time (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_y = 0.0;
double conf_camera_step_z = 0.0;
double conf_wind_x = 0.0;
double conf_wind_z = 0.0;
int outputcount;
char outputpath[500];
@ -107,6 +112,20 @@ int main(int argc, char** 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)
{
if (argc--)
@ -158,15 +177,15 @@ int main(int argc, char** argv)
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++)
{
if (conf_daytime_start >= 0.0)
{
AtmosphereDefinition* atmo = scenery->getAtmosphere();
atmo->setDayTime(conf_daytime_start);
atmo->validate();
}
CameraDefinition* camera = scenery->getCamera();
Vector3 step = {conf_camera_step_x, conf_camera_step_y, conf_camera_step_z};
camera->setLocation(camera->getLocation().add(step));
@ -182,7 +201,7 @@ int main(int argc, char** argv)
delete renderer;
conf_daytime_start += conf_daytime_step;
time.moveForward(scenery, conf_daytime_step);
}
printf("Cleaning up ...\n");

View file

@ -203,7 +203,6 @@ static void testNearFrustum()
scenery.autoPreset(3);
scenery.getCamera()->setLocation(Vector3(0.0, 0.0, 0.0));
scenery.getCamera()->setTarget(Vector3(1.0, 0.0, 1.0));
scenery.keepCameraAboveGround(scenery.getCamera());
SoftwareCanvasRenderer renderer(&scenery);
renderer.setSize(400, 300);
@ -231,6 +230,27 @@ static void testCloudsNearGround()
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()
{
testGroundShadowQuality();
@ -239,4 +259,5 @@ void runTestSuite()
testGodRays();
testNearFrustum();
testCloudsNearGround();
testSunNearHorizon();
}

View file

@ -10,6 +10,7 @@
#include "clouds/BaseCloudsModel.h"
#include "SurfaceMaterial.h"
#include "Logs.h"
#include "FloatNode.h"
#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);
}
@ -54,7 +55,7 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
double step_length, segment_length;
double min_step, max_step;
double noise_distance;
Vector3 walker, step, segment_start;
Vector3 walker, step, segment_start, offset;
double render_precision;
if (max_segments <= 0)
@ -80,7 +81,8 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
current_inside_length = 0.0;
segment_length = 0.0;
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;
step = direction.scale(render_precision);
@ -88,7 +90,7 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
{
walker = walker.add(step);
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;
if (noise_distance > 0.0)

View file

@ -69,6 +69,7 @@ SoftwareRenderer::~SoftwareRenderer()
void SoftwareRenderer::prepare()
{
scenery->validate();
scenery->getCamera()->copy(render_camera);
// Prepare sub renderers
// 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);
}
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;
double x, z;
@ -43,12 +43,12 @@ static inline Vector3 _getNormal(FractalNoise* noise, Vector3 base, double detai
z = base.z;
back.x = x;
back.y = _getHeight(noise, x, z + detail);
back.y = _getHeight(definition, noise, x, z + detail);
back.z = z + detail;
back = back.sub(base);
right.x = x + detail;
right.y = _getHeight(noise, x + detail, z);
right.y = _getHeight(definition, noise, x + detail, z);
right.z = z;
right = right.sub(base);
@ -89,26 +89,26 @@ static inline Color _getFoamMask(SoftwareRenderer* renderer, WaterDefinition* de
foam_factor = 0.0;
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)
{
foam_factor = normal_diff;
}
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)
{
foam_factor = normal_diff;
}
location.x += 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)
{
foam_factor = normal_diff;
}
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)
{
foam_factor = normal_diff;
@ -162,7 +162,7 @@ HeightInfo WaterRenderer::getHeightInfo()
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)
@ -176,7 +176,7 @@ WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z)
double reflection = definition->propReflection()->getValue();
location.x = x;
location.y = _getHeight(noise, x, z);
location.y = _getHeight(definition, noise, x, z);
location.z = z;
result.location = location;
@ -186,7 +186,7 @@ WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z)
detail = 0.00001;
}
normal = _getNormal(noise, location, detail);
normal = _getNormal(definition, noise, location, detail);
look_direction = location.sub(parent->getCameraLocation(location)).normalize();
/* Reflection */