Merge branch 'new_terrain_walker'
This commit is contained in:
commit
9c79ff51f9
16 changed files with 261 additions and 324 deletions
|
@ -64,3 +64,14 @@ void TexturesDefinition::applyPreset(TexturesPreset preset)
|
||||||
/* TODO */
|
/* TODO */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double TexturesDefinition::getMaximalDisplacement()
|
||||||
|
{
|
||||||
|
double result = 0.0;
|
||||||
|
int n = count();
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
result += getTextureLayer(i)->displacement_height;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ public:
|
||||||
TEXTURES_PRESET_CANYON
|
TEXTURES_PRESET_CANYON
|
||||||
} TexturesPreset;
|
} TexturesPreset;
|
||||||
void applyPreset(TexturesPreset preset);
|
void applyPreset(TexturesPreset preset);
|
||||||
|
|
||||||
|
double getMaximalDisplacement();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QSplashScreen>
|
|
||||||
|
|
||||||
#include "BasePreview.h"
|
#include "BasePreview.h"
|
||||||
#include "PreviewOsd.h"
|
#include "PreviewOsd.h"
|
||||||
|
@ -36,7 +35,6 @@ MainWindow* MainWindow::_instance = NULL;
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
MainWindow* window;
|
MainWindow* window;
|
||||||
QSplashScreen* splash;
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
@ -47,9 +45,6 @@ int main(int argc, char** argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
splash = new QSplashScreen(QPixmap(getDataPath("images/logo_256.png")));
|
|
||||||
splash->show();
|
|
||||||
|
|
||||||
QTranslator qtTranslator;
|
QTranslator qtTranslator;
|
||||||
QTranslator myTranslator;
|
QTranslator myTranslator;
|
||||||
|
|
||||||
|
@ -74,9 +69,6 @@ int main(int argc, char** argv)
|
||||||
window = new MainWindow();
|
window = new MainWindow();
|
||||||
window->show();
|
window->show();
|
||||||
//window->showMaximized();
|
//window->showMaximized();
|
||||||
splash->finish(window);
|
|
||||||
|
|
||||||
delete splash;
|
|
||||||
|
|
||||||
result = app.exec();
|
result = app.exec();
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ HEADERS += \
|
||||||
inputcamera.h \
|
inputcamera.h \
|
||||||
inputboolean.h \
|
inputboolean.h \
|
||||||
formwater.h \
|
formwater.h \
|
||||||
formtextures.h \
|
|
||||||
formrender.h \
|
formrender.h \
|
||||||
formclouds.h \
|
formclouds.h \
|
||||||
formatmosphere.h \
|
formatmosphere.h \
|
||||||
|
@ -74,7 +73,6 @@ SOURCES += \
|
||||||
inputcamera.cpp \
|
inputcamera.cpp \
|
||||||
inputboolean.cpp \
|
inputboolean.cpp \
|
||||||
formwater.cpp \
|
formwater.cpp \
|
||||||
formtextures.cpp \
|
|
||||||
formrender.cpp \
|
formrender.cpp \
|
||||||
formclouds.cpp \
|
formclouds.cpp \
|
||||||
formatmosphere.cpp \
|
formatmosphere.cpp \
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
#include "formtextures.h"
|
|
||||||
|
|
||||||
#include "DesktopScenery.h"
|
|
||||||
#include "BasePreview.h"
|
|
||||||
#include "tools.h"
|
|
||||||
#include "CameraDefinition.h"
|
|
||||||
#include "TexturesDefinition.h"
|
|
||||||
#include "TextureLayerDefinition.h"
|
|
||||||
#include "SoftwareRenderer.h"
|
|
||||||
#include "TerrainRenderer.h"
|
|
||||||
|
|
||||||
/**************** Previews ****************/
|
|
||||||
class PreviewTexturesCoverage : public BasePreview
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PreviewTexturesCoverage(QWidget* parent, TextureLayerDefinition* layer) : BasePreview(parent)
|
|
||||||
{
|
|
||||||
_renderer = new SoftwareRenderer();
|
|
||||||
_renderer->render_quality = 3;
|
|
||||||
|
|
||||||
_original_layer = layer;
|
|
||||||
|
|
||||||
addOsd(QString("geolocation"));
|
|
||||||
|
|
||||||
configScaling(20.0, 500.0, 20.0, 50.0);
|
|
||||||
configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
~PreviewTexturesCoverage()
|
|
||||||
{
|
|
||||||
delete _renderer;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
|
|
||||||
Color getColor(double x, double y)
|
|
||||||
{
|
|
||||||
Vector3 location;
|
|
||||||
Color result;
|
|
||||||
location.x = x;
|
|
||||||
location.y = _renderer->getTerrainRenderer()->getHeight(x, y, 1);
|
|
||||||
location.z = y;
|
|
||||||
//result.r = result.g = result.b = texturesGetLayerCoverage(_preview_layer, _renderer, location, this->scaling);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateData()
|
|
||||||
{
|
|
||||||
TexturesDefinition* textures = _renderer->getScenery()->getTextures();
|
|
||||||
textures->clear();
|
|
||||||
textures->addLayer();
|
|
||||||
_original_layer->copy(textures->getLayer(0));
|
|
||||||
|
|
||||||
_renderer->prepare();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SoftwareRenderer* _renderer;
|
|
||||||
TextureLayerDefinition* _original_layer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PreviewTexturesColor : public BasePreview
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PreviewTexturesColor(QWidget* parent, TextureLayerDefinition* layer) : BasePreview(parent)
|
|
||||||
{
|
|
||||||
_original_layer = layer;
|
|
||||||
|
|
||||||
_renderer = new SoftwareRenderer();
|
|
||||||
_renderer->render_quality = 3;
|
|
||||||
|
|
||||||
_renderer->render_camera->setLocation(Vector3(0.0, 20.0, 0.0));
|
|
||||||
|
|
||||||
configScaling(0.01, 1.0, 0.01, 0.1);
|
|
||||||
configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
~PreviewTexturesColor()
|
|
||||||
{
|
|
||||||
delete _renderer;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
|
|
||||||
Color getColor(double x, double y)
|
|
||||||
{
|
|
||||||
Vector3 location;
|
|
||||||
location.x = x;
|
|
||||||
location.y = 0.0;
|
|
||||||
location.z = y;
|
|
||||||
//return texturesGetLayerColor(_preview_layer, _renderer, location, this->scaling);
|
|
||||||
return COLOR_BLACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateData()
|
|
||||||
{
|
|
||||||
TexturesDefinition* textures = _renderer->getScenery()->getTextures();
|
|
||||||
textures->clear();
|
|
||||||
textures->addLayer();
|
|
||||||
_original_layer->copy(textures->getLayer(0));
|
|
||||||
|
|
||||||
_renderer->prepare();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
SoftwareRenderer* _renderer;
|
|
||||||
TextureLayerDefinition* _original_layer;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**************** Form ****************/
|
|
||||||
FormTextures::FormTextures(QWidget *parent) :
|
|
||||||
BaseFormLayer(parent)
|
|
||||||
{
|
|
||||||
addAutoPreset(tr("Rock"));
|
|
||||||
addAutoPreset(tr("Grass"));
|
|
||||||
addAutoPreset(tr("Sand"));
|
|
||||||
addAutoPreset(tr("Snow"));
|
|
||||||
|
|
||||||
_definition = new TexturesDefinition(NULL);
|
|
||||||
_layer = new TextureLayerDefinition(NULL);
|
|
||||||
|
|
||||||
_previewCoverage = new PreviewTexturesCoverage(this, _layer);
|
|
||||||
_previewColor = new PreviewTexturesColor(this, _layer);
|
|
||||||
addPreview(_previewCoverage, tr("Coverage preview"));
|
|
||||||
addPreview(_previewColor, tr("Lighted sample"));
|
|
||||||
|
|
||||||
addInputDouble(tr("Displacement height"), &_layer->displacement_height, 0.0, 0.1, 0.001, 0.01);
|
|
||||||
addInputDouble(tr("Displacement scaling"), &_layer->displacement_scaling, 0.003, 0.3, 0.003, 0.03);
|
|
||||||
addInputMaterial(tr("Material"), _layer->material);
|
|
||||||
/*addInputCurve(tr("Coverage by altitude"), _layer->terrain_zone->value_by_height, -20.0, 20.0, 0.0, 1.0, tr("Terrain altitude"), tr("Texture coverage"));
|
|
||||||
addInputCurve(tr("Coverage by slope"), _layer->terrain_zone->value_by_slope, 0.0, 5.0, 0.0, 1.0, tr("Terrain slope"), tr("Texture coverage"));*/
|
|
||||||
|
|
||||||
/*addInputDouble(tr("Amplitude for slope coverage"), &_layer->slope_range, 0.001, 0.1, 0.001, 0.01);
|
|
||||||
addInputDouble(tr("Layer thickness"), &_layer->thickness, 0.0, 0.1, 0.001, 0.01);
|
|
||||||
addInputDouble(tr("Transparency thickness"), &_layer->thickness_transparency, 0.0, 0.1, 0.001, 0.01);*/
|
|
||||||
|
|
||||||
setLayers(_definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
FormTextures::~FormTextures()
|
|
||||||
{
|
|
||||||
delete _definition;
|
|
||||||
delete _layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormTextures::revertConfig()
|
|
||||||
{
|
|
||||||
DesktopScenery::getCurrent()->getTextures(_definition);
|
|
||||||
BaseFormLayer::revertConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormTextures::applyConfig()
|
|
||||||
{
|
|
||||||
BaseFormLayer::applyConfig();
|
|
||||||
DesktopScenery::getCurrent()->setTextures(_definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormTextures::layerReadCurrentFrom(void* layer_definition)
|
|
||||||
{
|
|
||||||
((TextureLayerDefinition*)layer_definition)->copy(_layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormTextures::layerWriteCurrentTo(void* layer_definition)
|
|
||||||
{
|
|
||||||
_layer->copy((TextureLayerDefinition*)layer_definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormTextures::autoPresetSelected(int preset)
|
|
||||||
{
|
|
||||||
_layer->applyPreset((TextureLayerDefinition::TextureLayerPreset)preset);
|
|
||||||
BaseForm::autoPresetSelected(preset);
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef _PAYSAGES_QT_FORMTEXTURES_H_
|
|
||||||
#define _PAYSAGES_QT_FORMTEXTURES_H_
|
|
||||||
|
|
||||||
#include "desktop_global.h"
|
|
||||||
|
|
||||||
#include "baseformlayer.h"
|
|
||||||
|
|
||||||
class QWidget;
|
|
||||||
|
|
||||||
class FormTextures : public BaseFormLayer
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FormTextures(QWidget *parent = 0);
|
|
||||||
~FormTextures();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
virtual void revertConfig();
|
|
||||||
virtual void applyConfig();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void layerReadCurrentFrom(void* layer_definition);
|
|
||||||
virtual void layerWriteCurrentTo(void* layer_definition);
|
|
||||||
virtual void autoPresetSelected(int preset);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TexturesDefinition* _definition;
|
|
||||||
TextureLayerDefinition* _layer;
|
|
||||||
BasePreview* _previewCoverage;
|
|
||||||
BasePreview* _previewColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "common/freeformhelper.h"
|
#include "common/freeformhelper.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "DesktopScenery.h"
|
#include "DesktopScenery.h"
|
||||||
|
#include "TexturesDefinition.h"
|
||||||
#include "TerrainDefinition.h"
|
#include "TerrainDefinition.h"
|
||||||
#include "TerrainHeightMap.h"
|
#include "TerrainHeightMap.h"
|
||||||
|
|
||||||
|
@ -70,8 +71,7 @@ void MainTerrainForm::refreshFromLocalData()
|
||||||
|
|
||||||
void MainTerrainForm::refreshFromFellowData()
|
void MainTerrainForm::refreshFromFellowData()
|
||||||
{
|
{
|
||||||
//double disp = texturesGetMaximalDisplacement(RenderingScenery::getCurrent()->getTextures());
|
double disp = DesktopScenery::getCurrent()->getTextures()->getMaximalDisplacement();
|
||||||
double disp = -1000.0;
|
|
||||||
|
|
||||||
if (disp == 0.0)
|
if (disp == 0.0)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,9 @@ void MainTerrainForm::refreshFromFellowData()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ui->label_info_textures->setText(tr("Maximal displacement : %1% of total height").arg(100.0 * disp / _terrain->height, 0, 'f', 1));
|
HeightInfo info = DesktopScenery::getCurrent()->getTerrain()->getHeightInfo();
|
||||||
|
double terrain_height = info.max_height - info.min_height;
|
||||||
|
ui->label_info_textures->setText(tr("Maximal displacement : %1% of total height").arg(100.0 * disp / terrain_height, 0, 'f', 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ OpenGLRenderer::OpenGLRenderer(Scenery* scenery):
|
||||||
{
|
{
|
||||||
ready = false;
|
ready = false;
|
||||||
|
|
||||||
|
render_quality = 3;
|
||||||
|
|
||||||
functions = new OpenGLFunctions();
|
functions = new OpenGLFunctions();
|
||||||
shared_state = new OpenGLSharedState();
|
shared_state = new OpenGLSharedState();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ SceneryTopDownPreviewRenderer::SceneryTopDownPreviewRenderer(Scenery* scenery):
|
||||||
scenery(scenery)
|
scenery(scenery)
|
||||||
{
|
{
|
||||||
clouds_enabled = true;
|
clouds_enabled = true;
|
||||||
|
render_quality = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneryTopDownPreviewRenderer::bindEvent(BasePreview* preview)
|
void SceneryTopDownPreviewRenderer::bindEvent(BasePreview* preview)
|
||||||
|
|
|
@ -134,16 +134,16 @@ void SoftwareRenderer::disableAtmosphere()
|
||||||
light.color.g = 1.5;
|
light.color.g = 1.5;
|
||||||
light.color.b = 1.5;
|
light.color.b = 1.5;
|
||||||
light.direction.x = -1.0;
|
light.direction.x = -1.0;
|
||||||
light.direction.y = -0.5;
|
light.direction.y = -0.3;
|
||||||
light.direction.z = 1.0;
|
light.direction.z = 1.0;
|
||||||
light.direction = light.direction.normalize();
|
light.direction = light.direction.normalize();
|
||||||
light.altered = 1;
|
light.altered = 1;
|
||||||
light.reflection = 0.0;
|
light.reflection = 0.0;
|
||||||
lights.push_back(light);
|
lights.push_back(light);
|
||||||
|
|
||||||
light.color.r = 0.4;
|
light.color.r = 0.2;
|
||||||
light.color.g = 0.4;
|
light.color.g = 0.2;
|
||||||
light.color.b = 0.42;
|
light.color.b = 0.21;
|
||||||
light.direction.x = 1.0;
|
light.direction.x = 1.0;
|
||||||
light.direction.y = -0.5;
|
light.direction.y = -0.5;
|
||||||
light.direction.z = -1.0;
|
light.direction.z = -1.0;
|
||||||
|
|
137
src/render/software/TerrainRayWalker.cpp
Normal file
137
src/render/software/TerrainRayWalker.cpp
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
#include "TerrainRayWalker.h"
|
||||||
|
|
||||||
|
#include "SoftwareRenderer.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
#include "TerrainDefinition.h"
|
||||||
|
#include "TexturesDefinition.h"
|
||||||
|
#include "TerrainRenderer.h"
|
||||||
|
#include "TexturesRenderer.h"
|
||||||
|
#include "Matrix4.h"
|
||||||
|
|
||||||
|
TerrainRayWalker::TerrainRayWalker(SoftwareRenderer* renderer):
|
||||||
|
renderer(renderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainRayWalker::update()
|
||||||
|
{
|
||||||
|
TerrainDefinition* terrain = renderer->getScenery()->getTerrain();
|
||||||
|
HeightInfo info = terrain->getHeightInfo();
|
||||||
|
|
||||||
|
TexturesDefinition* textures = renderer->getScenery()->getTextures();
|
||||||
|
double disp = textures->getMaximalDisplacement();
|
||||||
|
|
||||||
|
ymin = info.min_height - disp;
|
||||||
|
ymax = info.max_height + disp;
|
||||||
|
|
||||||
|
ydispmax = disp * (0.5 + (double)renderer->render_quality * 0.1);
|
||||||
|
ydispmin = -ydispmax;
|
||||||
|
|
||||||
|
minstep = 1.0 * terrain->scaling / (double)(renderer->render_quality * renderer->render_quality);
|
||||||
|
maxstep = 10.0 * terrain->scaling / (double)renderer->render_quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Vector3 _getShiftAxis(const Vector3 &direction)
|
||||||
|
{
|
||||||
|
if (fabs(direction.y) > 0.99)
|
||||||
|
{
|
||||||
|
// When the ray is vertical, we choose an arbitrary shift axis
|
||||||
|
return VECTOR_NORTH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return VECTOR_UP.crossProduct(direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TerrainRayWalker::startWalking(const Vector3 &start, Vector3 direction, double escape_angle, double max_length, TerrainHitResult &result)
|
||||||
|
{
|
||||||
|
TerrainRenderer* terrain_renderer = renderer->getTerrainRenderer();
|
||||||
|
TexturesRenderer* textures_renderer = renderer->getTexturesRenderer();
|
||||||
|
TerrainRenderer::TerrainResult terrain_result;
|
||||||
|
Vector3 cursor, displaced;
|
||||||
|
double diff;
|
||||||
|
Matrix4 shift_matrix;
|
||||||
|
double shift_step = 0.0;
|
||||||
|
|
||||||
|
Vector3 previous_cursor = start;
|
||||||
|
bool hit = false;
|
||||||
|
double step_length = minstep;
|
||||||
|
double walked_length = 0.0;
|
||||||
|
|
||||||
|
result.escape_angle = 0.0;
|
||||||
|
if (escape_angle != 0.0)
|
||||||
|
{
|
||||||
|
// Prepare escape
|
||||||
|
shift_step = escape_angle / (double)(renderer->render_quality * renderer->render_quality);
|
||||||
|
shift_matrix = Matrix4::newRotateAxis(-shift_step, _getShiftAxis(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Perform a step
|
||||||
|
cursor = previous_cursor.add(direction.scale(step_length));
|
||||||
|
|
||||||
|
// Get the terrain info at end (without textures displacement)
|
||||||
|
terrain_result = terrain_renderer->getResult(cursor.x, cursor.z, true, false);
|
||||||
|
diff = cursor.y - terrain_result.location.y;
|
||||||
|
|
||||||
|
// If we are very under the terrain, consider a hit
|
||||||
|
if (diff < ydispmin)
|
||||||
|
{
|
||||||
|
hit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are close enough to the terrain, apply displacement
|
||||||
|
else if (diff < ydispmax)
|
||||||
|
{
|
||||||
|
displaced = textures_renderer->displaceTerrain(terrain_result);
|
||||||
|
diff = cursor.y - displaced.y;
|
||||||
|
hit = diff < 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hit)
|
||||||
|
{
|
||||||
|
// TODO Refine the hit with dichotomy at high quality
|
||||||
|
/*if (renderer->render_quality > 7)
|
||||||
|
{
|
||||||
|
cursor = refineHit(previous_cursor, cursor, step_length);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Shift ray to escape terrain
|
||||||
|
if (escape_angle != 0.0)
|
||||||
|
{
|
||||||
|
result.escape_angle += shift_step;
|
||||||
|
if (result.escape_angle > escape_angle)
|
||||||
|
{
|
||||||
|
// Too much shifted to escape, make it a hit
|
||||||
|
result.escape_angle = 0.0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
hit = false;
|
||||||
|
direction = shift_matrix.multPoint(direction);
|
||||||
|
previous_cursor = start.add(shift_matrix.multPoint(previous_cursor.sub(start)));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.hit_location = cursor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Prepare next step
|
||||||
|
previous_cursor = cursor;
|
||||||
|
walked_length += step_length;
|
||||||
|
|
||||||
|
step_length = diff * 3.0 / (double)renderer->render_quality;
|
||||||
|
if (step_length < minstep)
|
||||||
|
{
|
||||||
|
step_length = minstep;
|
||||||
|
}
|
||||||
|
else if (step_length > maxstep)
|
||||||
|
{
|
||||||
|
step_length = maxstep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (not hit and cursor.y < ymax and walked_length < max_length);
|
||||||
|
|
||||||
|
return hit or result.escape_angle > 0.0;
|
||||||
|
}
|
59
src/render/software/TerrainRayWalker.h
Normal file
59
src/render/software/TerrainRayWalker.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef TERRAINRAYWALKER_H
|
||||||
|
#define TERRAINRAYWALKER_H
|
||||||
|
|
||||||
|
#include "software_global.h"
|
||||||
|
|
||||||
|
#include "Vector3.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace software {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Ray walker to find intersections with terrain.
|
||||||
|
*
|
||||||
|
* This walker can be used to find a hard intersection between
|
||||||
|
* a ray and the terrain (e.g. for raytracing), or a soft intersection
|
||||||
|
* (e.g. for shadows).
|
||||||
|
*/
|
||||||
|
class SOFTWARESHARED_EXPORT TerrainRayWalker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
Vector3 hit_location; // Location of the hit
|
||||||
|
double escape_angle; // Angle used to shift the ray to escape the terrain (0.0 if no escape was possible)
|
||||||
|
} TerrainHitResult;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TerrainRayWalker(SoftwareRenderer* renderer);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Update the walker internal data, from the renderer and scenery.
|
||||||
|
*/
|
||||||
|
void update();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Start the walking process to find intersection
|
||||||
|
*
|
||||||
|
* \param start Point of origin of the ray
|
||||||
|
* \param direction Ray direction (normalized vector)
|
||||||
|
* \param escape_angle Maximal angle allowed to escape the terrain on hit (mainly for shadows computing)
|
||||||
|
* \param max_length Maximum length to walk before considering no hit
|
||||||
|
* \param result Object to store the results info
|
||||||
|
* \return true if there was a hit
|
||||||
|
*/
|
||||||
|
bool startWalking(const Vector3 &start, Vector3 direction, double escape_angle, double max_length, TerrainHitResult &result);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SoftwareRenderer* renderer;
|
||||||
|
double ymin;
|
||||||
|
double ymax;
|
||||||
|
double ydispmin;
|
||||||
|
double ydispmax;
|
||||||
|
double minstep;
|
||||||
|
double maxstep;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TERRAINRAYWALKER_H
|
|
@ -5,18 +5,22 @@
|
||||||
#include "TerrainDefinition.h"
|
#include "TerrainDefinition.h"
|
||||||
#include "TexturesRenderer.h"
|
#include "TexturesRenderer.h"
|
||||||
#include "LightComponent.h"
|
#include "LightComponent.h"
|
||||||
|
#include "TerrainRayWalker.h"
|
||||||
|
|
||||||
TerrainRenderer::TerrainRenderer(SoftwareRenderer* parent):
|
TerrainRenderer::TerrainRenderer(SoftwareRenderer* parent):
|
||||||
parent(parent)
|
parent(parent)
|
||||||
{
|
{
|
||||||
|
walker = new TerrainRayWalker(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainRenderer::~TerrainRenderer()
|
TerrainRenderer::~TerrainRenderer()
|
||||||
{
|
{
|
||||||
|
delete walker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainRenderer::update()
|
void TerrainRenderer::update()
|
||||||
{
|
{
|
||||||
|
walker->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
double TerrainRenderer::getHeight(double x, double z, int with_painting)
|
double TerrainRenderer::getHeight(double x, double z, int with_painting)
|
||||||
|
@ -130,75 +134,33 @@ Color TerrainRenderer::getFinalColor(const Vector3 &location, double)
|
||||||
RayCastingResult TerrainRenderer::castRay(const Vector3 &start, const Vector3 &direction)
|
RayCastingResult TerrainRenderer::castRay(const Vector3 &start, const Vector3 &direction)
|
||||||
{
|
{
|
||||||
RayCastingResult result;
|
RayCastingResult result;
|
||||||
TerrainDefinition* definition = parent->getScenery()->getTerrain();
|
TerrainRayWalker::TerrainHitResult walk_result;
|
||||||
Vector3 inc_vector, direction_norm, cursor;
|
if (walker->startWalking(start, direction.normalize(), 0.0, 200.0, walk_result))
|
||||||
double inc_value, inc_base, inc_factor, height, diff, lastdiff, length;
|
|
||||||
|
|
||||||
cursor = start;
|
|
||||||
direction_norm = direction.normalize();
|
|
||||||
inc_factor = (double)parent->render_quality;
|
|
||||||
inc_base = 1.0;
|
|
||||||
inc_value = inc_base / inc_factor;
|
|
||||||
lastdiff = start.y - getHeight(start.x, start.z, 1);
|
|
||||||
|
|
||||||
length = 0.0;
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
inc_vector = direction_norm.scale(inc_value);
|
result.hit = true;
|
||||||
length += inc_vector.getNorm();
|
result.hit_location = walk_result.hit_location;
|
||||||
cursor = cursor.add(inc_vector);
|
result.hit_color = getFinalColor(walk_result.hit_location, parent->getPrecision(walk_result.hit_location));
|
||||||
height = getHeight(cursor.x, cursor.z, 1);
|
|
||||||
diff = cursor.y - height;
|
|
||||||
if (diff < 0.0)
|
|
||||||
{
|
|
||||||
if (fabs(diff - lastdiff) > 0.00001)
|
|
||||||
{
|
|
||||||
cursor = cursor.add(inc_vector.scale(-diff / (diff - lastdiff)));
|
|
||||||
cursor.y = getHeight(cursor.x, cursor.z, 1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cursor.y = height;
|
result.hit = false;
|
||||||
}
|
}
|
||||||
result.hit = 1;
|
|
||||||
result.hit_location = cursor;
|
|
||||||
result.hit_color = getFinalColor(cursor, parent->getPrecision(result.hit_location));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diff < inc_base / inc_factor)
|
|
||||||
{
|
|
||||||
inc_value = inc_base / inc_factor;
|
|
||||||
}
|
|
||||||
else if (diff > inc_base)
|
|
||||||
{
|
|
||||||
inc_value = inc_base;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inc_value = diff;
|
|
||||||
}
|
|
||||||
lastdiff = diff;
|
|
||||||
}
|
|
||||||
while (length < 50.0 && cursor.y <= definition->_max_height);
|
|
||||||
|
|
||||||
result.hit = 0;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TerrainRenderer::applyLightFilter(LightComponent &light, const Vector3 &at)
|
bool TerrainRenderer::applyLightFilter(LightComponent &light, const Vector3 &at)
|
||||||
{
|
{
|
||||||
TerrainDefinition* definition = parent->getScenery()->getTerrain();
|
TerrainDefinition* definition = parent->getScenery()->getTerrain();
|
||||||
Vector3 inc_vector, direction_to_light, cursor;
|
TerrainRayWalker::TerrainHitResult walk_result;
|
||||||
double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length;
|
|
||||||
|
|
||||||
|
// If location is above terrain, don't bother
|
||||||
if (at.y > definition->getHeightInfo().max_height)
|
if (at.y > definition->getHeightInfo().max_height)
|
||||||
{
|
{
|
||||||
// Location is above terrain, don't bother
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
direction_to_light = light.direction.scale(-1.0);
|
// Handle sun below horizon
|
||||||
|
Vector3 direction_to_light = light.direction.scale(-1.0);
|
||||||
if (direction_to_light.y < -0.05)
|
if (direction_to_light.y < -0.05)
|
||||||
{
|
{
|
||||||
light.color = COLOR_BLACK;
|
light.color = COLOR_BLACK;
|
||||||
|
@ -211,56 +173,21 @@ bool TerrainRenderer::applyLightFilter(LightComponent &light, const Vector3 &at)
|
||||||
light.color.b *= (0.05 + direction_to_light.y) / 0.05;
|
light.color.b *= (0.05 + direction_to_light.y) / 0.05;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = at;
|
// Walk to find an intersection
|
||||||
inc_factor = (double)parent->render_quality;
|
double escape_angle = definition->shadow_smoothing;
|
||||||
inc_base = definition->height / definition->scaling;
|
if (walker->startWalking(at, direction_to_light, escape_angle, 100.0, walk_result))
|
||||||
inc_value = inc_base / inc_factor;
|
|
||||||
smoothing = definition->shadow_smoothing;
|
|
||||||
|
|
||||||
light_factor = 1.0;
|
|
||||||
length = 0.0;
|
|
||||||
diff = 0.0;
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
inc_vector = direction_to_light.scale(inc_value);
|
if (walk_result.escape_angle == 0.0)
|
||||||
length += inc_vector.getNorm();
|
|
||||||
cursor = cursor.add(inc_vector);
|
|
||||||
height = parent->getTerrainRenderer()->getResult(cursor.x, cursor.z, 1, 1).location.y;
|
|
||||||
diff = cursor.y - height;
|
|
||||||
if (diff < 0.0)
|
|
||||||
{
|
|
||||||
if (length * smoothing > 0.000001)
|
|
||||||
{
|
|
||||||
light_factor += diff * inc_vector.getNorm() / (length * smoothing);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
light_factor = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diff < inc_base / inc_factor)
|
|
||||||
{
|
|
||||||
inc_value = inc_base / inc_factor;
|
|
||||||
}
|
|
||||||
else if (diff > inc_base)
|
|
||||||
{
|
|
||||||
inc_value = inc_base;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inc_value = diff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (light_factor > 0.0 && length < (10.0 * inc_factor) && cursor.y <= definition->_max_height);
|
|
||||||
|
|
||||||
if (light_factor <= 0.0)
|
|
||||||
{
|
{
|
||||||
|
// Hit, with no escape, cancelling the light
|
||||||
light.color = COLOR_BLACK;
|
light.color = COLOR_BLACK;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Hit, with an escape
|
||||||
|
double light_factor = 1.0 - (walk_result.escape_angle / escape_angle);
|
||||||
|
|
||||||
light.color.r *= light_factor;
|
light.color.r *= light_factor;
|
||||||
light.color.g *= light_factor;
|
light.color.g *= light_factor;
|
||||||
light.color.b *= light_factor;
|
light.color.b *= light_factor;
|
||||||
|
@ -268,6 +195,12 @@ bool TerrainRenderer::applyLightFilter(LightComponent &light, const Vector3 &at)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No hit, leave light alone
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double TerrainRenderer::getWaterHeight()
|
double TerrainRenderer::getWaterHeight()
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SoftwareRenderer* parent;
|
SoftwareRenderer* parent;
|
||||||
|
TerrainRayWalker* walker;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ SOURCES += SoftwareRenderer.cpp \
|
||||||
WaterRenderer.cpp \
|
WaterRenderer.cpp \
|
||||||
RenderArea.cpp \
|
RenderArea.cpp \
|
||||||
RayCastingManager.cpp \
|
RayCastingManager.cpp \
|
||||||
NightSky.cpp
|
NightSky.cpp \
|
||||||
|
TerrainRayWalker.cpp
|
||||||
|
|
||||||
HEADERS += SoftwareRenderer.h\
|
HEADERS += SoftwareRenderer.h\
|
||||||
software_global.h \
|
software_global.h \
|
||||||
|
@ -62,7 +63,8 @@ HEADERS += SoftwareRenderer.h\
|
||||||
WaterRenderer.h \
|
WaterRenderer.h \
|
||||||
RenderArea.h \
|
RenderArea.h \
|
||||||
RayCastingManager.h \
|
RayCastingManager.h \
|
||||||
NightSky.h
|
NightSky.h \
|
||||||
|
TerrainRayWalker.h
|
||||||
|
|
||||||
unix:!symbian {
|
unix:!symbian {
|
||||||
maemo5 {
|
maemo5 {
|
||||||
|
|
|
@ -42,6 +42,8 @@ namespace software {
|
||||||
class LightComponent;
|
class LightComponent;
|
||||||
|
|
||||||
class NightSky;
|
class NightSky;
|
||||||
|
|
||||||
|
class TerrainRayWalker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue