Harald Johnson:
Changes ======= - corrected some strange behavior when playing with the render dialog options - the density slider is now working : if you are fps limited and still want to see clouds in the distance you should play with that - added the choice for texture resolution, its more comprehensible now (before it was wrongly allways choosing 64x64 textures) - changed the initial texture size : you now have 64 texture of 64x64, this uses 1Mo of texture memory (before it was 20 texture of 256x256, that took more memory and there was not enought impostors) - sun vector is now right so the lighting is a bit better - removed useless sort and light computations for impostors, this should save a lot of cpu - blending of distant cloud is more accurate now - clouds are now positioned correctly, they don't try to escape you anymore - no more red/white boxes around cloud - textures are now filtered (no more big pixels) known bugs ========== - distant objects are seen in front of clouds
This commit is contained in:
parent
9048ee533d
commit
d37992aaf9
@ -26,12 +26,38 @@
|
|||||||
|
|
||||||
SGEnviro sgEnviro;
|
SGEnviro sgEnviro;
|
||||||
|
|
||||||
SGEnviro::SGEnviro(void) {
|
SGEnviro::SGEnviro(void) :
|
||||||
|
view_in_cloud(false),
|
||||||
|
precipitation_enable_state(false),
|
||||||
|
precipitation_density(100.0)
|
||||||
|
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SGEnviro::~SGEnviro(void) {
|
SGEnviro::~SGEnviro(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SGEnviro::startOfFrame(void) {
|
||||||
|
view_in_cloud = false;
|
||||||
|
if(SGNewCloud::cldCache)
|
||||||
|
SGNewCloud::cldCache->startNewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SGEnviro::endOfFrame(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// this can be queried to add some turbulence for example
|
||||||
|
bool SGEnviro::is_view_in_cloud(void) const {
|
||||||
|
return view_in_cloud;
|
||||||
|
}
|
||||||
|
void SGEnviro::set_view_in_cloud(bool incloud) {
|
||||||
|
view_in_cloud = incloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SGEnviro::get_CacheResolution(void) const {
|
||||||
|
return SGCloudField::get_CacheResolution();
|
||||||
|
}
|
||||||
|
|
||||||
int SGEnviro::get_clouds_CacheSize(void) const {
|
int SGEnviro::get_clouds_CacheSize(void) const {
|
||||||
return SGCloudField::get_CacheSize();
|
return SGCloudField::get_CacheSize();
|
||||||
}
|
}
|
||||||
@ -45,6 +71,10 @@ bool SGEnviro::get_clouds_enable_state(void) const {
|
|||||||
return SGCloudField::get_enable3dClouds();
|
return SGCloudField::get_enable3dClouds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SGEnviro::set_CacheResolution(int resolutionPixels) {
|
||||||
|
SGCloudField::set_CacheResolution(resolutionPixels);
|
||||||
|
}
|
||||||
|
|
||||||
void SGEnviro::set_clouds_CacheSize(int sizeKb) {
|
void SGEnviro::set_clouds_CacheSize(int sizeKb) {
|
||||||
SGCloudField::set_CacheSize(sizeKb);
|
SGCloudField::set_CacheSize(sizeKb);
|
||||||
}
|
}
|
||||||
@ -60,15 +90,17 @@ void SGEnviro::set_clouds_enable_state(bool enable) {
|
|||||||
|
|
||||||
// rain/snow
|
// rain/snow
|
||||||
float SGEnviro::get_precipitation_density(void) const {
|
float SGEnviro::get_precipitation_density(void) const {
|
||||||
return 0.0;
|
return precipitation_density;
|
||||||
}
|
}
|
||||||
bool SGEnviro::get_precipitation_enable_state(void) const {
|
bool SGEnviro::get_precipitation_enable_state(void) const {
|
||||||
return false;
|
return precipitation_enable_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SGEnviro::set_precipitation_density(float density) {
|
void SGEnviro::set_precipitation_density(float density) {
|
||||||
|
precipitation_density = density;
|
||||||
}
|
}
|
||||||
void SGEnviro::set_precipitation_enable_state(bool enable) {
|
void SGEnviro::set_precipitation_enable_state(bool enable) {
|
||||||
|
precipitation_enable_state = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// others
|
// others
|
||||||
|
@ -24,18 +24,32 @@
|
|||||||
|
|
||||||
class SGEnviro {
|
class SGEnviro {
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool view_in_cloud;
|
||||||
|
bool precipitation_enable_state;
|
||||||
|
float precipitation_density;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SGEnviro();
|
SGEnviro();
|
||||||
~SGEnviro();
|
~SGEnviro();
|
||||||
|
|
||||||
|
void startOfFrame(void);
|
||||||
|
void endOfFrame(void);
|
||||||
|
|
||||||
|
// this can be queried to add some turbulence for example
|
||||||
|
bool is_view_in_cloud(void) const;
|
||||||
|
void set_view_in_cloud(bool incloud);
|
||||||
|
|
||||||
// Clouds
|
// Clouds
|
||||||
// return the size of the memory pool used by texture impostors
|
// return the size of the memory pool used by texture impostors
|
||||||
int get_clouds_CacheSize(void) const;
|
int get_clouds_CacheSize(void) const;
|
||||||
|
int get_CacheResolution(void) const;
|
||||||
float get_clouds_visibility(void) const;
|
float get_clouds_visibility(void) const;
|
||||||
float get_clouds_density(void) const;
|
float get_clouds_density(void) const;
|
||||||
bool get_clouds_enable_state(void) const;
|
bool get_clouds_enable_state(void) const;
|
||||||
|
|
||||||
void set_clouds_CacheSize(int sizeKb);
|
void set_clouds_CacheSize(int sizeKb);
|
||||||
|
void set_CacheResolution(int resolutionPixels);
|
||||||
void set_clouds_visibility(float distance);
|
void set_clouds_visibility(float distance);
|
||||||
void set_clouds_density(float density);
|
void set_clouds_density(float density);
|
||||||
void set_clouds_enable_state(bool enable);
|
void set_clouds_enable_state(bool enable);
|
||||||
@ -55,4 +69,3 @@ public:
|
|||||||
extern SGEnviro sgEnviro;
|
extern SGEnviro sgEnviro;
|
||||||
|
|
||||||
#endif // _VISUAL_ENVIRO_HXX
|
#endif // _VISUAL_ENVIRO_HXX
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ bool SGBbCache::allocTextureMemory(int cacheCount, int textureDimension) {
|
|||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
cacheSizeKb = (textureDimension * textureDimension * 4);
|
cacheSizeKb = (textureDimension * textureDimension * 4);
|
||||||
@ -94,7 +94,7 @@ SGBbCache::SGBbCache(void) :
|
|||||||
rt(0),
|
rt(0),
|
||||||
rtAvailable(false),
|
rtAvailable(false),
|
||||||
frameNumber(0),
|
frameNumber(0),
|
||||||
maxImpostorRegenFrame(10)
|
maxImpostorRegenFrame(20)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,11 +139,11 @@ void SGBbCache::init(int cacheCount) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( cacheCount )
|
if( cacheCount )
|
||||||
allocTextureMemory( cacheCount, 256 );
|
allocTextureMemory( cacheCount, 64 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:not callable atm, texture size not handled correctly
|
|
||||||
bool SGBbCache::setCacheSize(int count, int textureDimension) {
|
bool SGBbCache::setCacheSize(int count, int textureDimension) {
|
||||||
if( count < 0 || count > 500)
|
if( count < 0 || count > 500)
|
||||||
return false;
|
return false;
|
||||||
@ -172,7 +172,7 @@ bool SGBbCache::setCacheSize(int count, int textureDimension) {
|
|||||||
return allocTextureMemory( count, textureDimension);
|
return allocTextureMemory( count, textureDimension);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:not callable atm, texture size not handled correctly
|
|
||||||
bool SGBbCache::setCacheSize(int sizeKb) {
|
bool SGBbCache::setCacheSize(int sizeKb) {
|
||||||
if( sizeKb < 0 || sizeKb > 256*1024)
|
if( sizeKb < 0 || sizeKb > 256*1024)
|
||||||
return false;
|
return false;
|
||||||
@ -181,10 +181,10 @@ bool SGBbCache::setCacheSize(int sizeKb) {
|
|||||||
return true;
|
return true;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
int textureDimension = 256;
|
int textureDimension = 256;
|
||||||
if( cacheSizeKb >= 8*1024 ) {
|
if( sizeKb >= 8*1024 ) {
|
||||||
// more than 32 256x256 textures
|
// more than 32 256x256 textures
|
||||||
textureDimension = 256;
|
textureDimension = 256;
|
||||||
} else if( cacheSizeKb >= 2*1024 ) {
|
} else if( sizeKb >= 2*1024 ) {
|
||||||
// more than 32 128x128 textures
|
// more than 32 128x128 textures
|
||||||
textureDimension = 128;
|
textureDimension = 128;
|
||||||
} else {
|
} else {
|
||||||
@ -305,10 +305,10 @@ bool SGBbCache::isBbValid( int cldId, int bbId, float angleY, float angleX) {
|
|||||||
if( builtBBframe >= maxImpostorRegenFrame )
|
if( builtBBframe >= maxImpostorRegenFrame )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( fabs(angleY - bbList[bbId].angleY) >= 5.0 )
|
if( fabs(angleY - bbList[bbId].angleY) >= 4.0 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( fabs(angleX - bbList[bbId].angleX) >= 5.0 )
|
if( fabs(angleX - bbList[bbId].angleX) >= 4.0 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bbList[bbId].frameUsed = frameNumber;
|
bbList[bbId].frameUsed = frameNumber;
|
||||||
|
@ -29,12 +29,14 @@
|
|||||||
#include <plib/sg.h>
|
#include <plib/sg.h>
|
||||||
#include <plib/ssg.h>
|
#include <plib/ssg.h>
|
||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
|
#include <simgear/math/polar3d.hxx>
|
||||||
|
|
||||||
#include STL_ALGORITHM
|
#include STL_ALGORITHM
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
SG_USING_STD(vector);
|
SG_USING_STD(vector);
|
||||||
|
|
||||||
|
#include <simgear/environment/visual_enviro.hxx>
|
||||||
#include "newcloud.hxx"
|
#include "newcloud.hxx"
|
||||||
#include "cloudfield.hxx"
|
#include "cloudfield.hxx"
|
||||||
|
|
||||||
@ -45,9 +47,26 @@ float SGCloudField::CloudVis = 25000.0f;
|
|||||||
bool SGCloudField::enable3D = true;
|
bool SGCloudField::enable3D = true;
|
||||||
// fieldSize must be > CloudVis or we can destroy the impostor cache
|
// fieldSize must be > CloudVis or we can destroy the impostor cache
|
||||||
// a cloud must only be seen once or the impostor will be generated for each of his positions
|
// a cloud must only be seen once or the impostor will be generated for each of his positions
|
||||||
double SGCloudField::fieldSize = 30000.0;
|
double SGCloudField::fieldSize = 27000.0;
|
||||||
float SGCloudField::density = 100.0;
|
float SGCloudField::density = 100.0;
|
||||||
static int last_cache_size = 4*1024;
|
static int last_cache_size = 1*1024;
|
||||||
|
static int cacheResolution = 64;
|
||||||
|
|
||||||
|
int SGCloudField::get_CacheResolution(void) {
|
||||||
|
return cacheResolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SGCloudField::set_CacheResolution(int resolutionPixels) {
|
||||||
|
if(cacheResolution == resolutionPixels)
|
||||||
|
return;
|
||||||
|
cacheResolution = resolutionPixels;
|
||||||
|
if(enable3D) {
|
||||||
|
int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4);
|
||||||
|
if(count == 0)
|
||||||
|
count = 1;
|
||||||
|
SGNewCloud::cldCache->setCacheSize(count, cacheResolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int SGCloudField::get_CacheSize(void) {
|
int SGCloudField::get_CacheSize(void) {
|
||||||
return SGNewCloud::cldCache->queryCacheSize();
|
return SGNewCloud::cldCache->queryCacheSize();
|
||||||
@ -61,9 +80,16 @@ void SGCloudField::set_CacheSize(int sizeKb) {
|
|||||||
return;
|
return;
|
||||||
if(sizeKb)
|
if(sizeKb)
|
||||||
last_cache_size = sizeKb;
|
last_cache_size = sizeKb;
|
||||||
SGNewCloud::cldCache->setCacheSize(sizeKb);
|
if(enable3D) {
|
||||||
|
int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4);
|
||||||
|
if(count == 0)
|
||||||
|
count = 1;
|
||||||
|
// SGNewCloud::cldCache->setCacheSize(sizeKb);
|
||||||
|
SGNewCloud::cldCache->setCacheSize(count, cacheResolution);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void SGCloudField::set_CloudVis(float distance) {
|
void SGCloudField::set_CloudVis(float distance) {
|
||||||
|
if( distance <= fieldSize )
|
||||||
SGCloudField::CloudVis = distance;
|
SGCloudField::CloudVis = distance;
|
||||||
}
|
}
|
||||||
void SGCloudField::set_density(float density) {
|
void SGCloudField::set_density(float density) {
|
||||||
@ -104,15 +130,7 @@ void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, doub
|
|||||||
|
|
||||||
sgMakeCoordMat4( transform, &layerpos );
|
sgMakeCoordMat4( transform, &layerpos );
|
||||||
|
|
||||||
// TODO:use a simple sphere earth
|
|
||||||
double az1, az2, s;
|
|
||||||
geo_inverse_wgs_84( 0.0, 0.0, 0.0, lat*SG_RADIANS_TO_DEGREES , lon*SG_RADIANS_TO_DEGREES, &az1, &az2, &s);
|
|
||||||
az1 = az1 * SG_DEGREES_TO_RADIANS;
|
|
||||||
// compute the view position on a 'flat' earth
|
|
||||||
deltay = -cos(SG_PI/2+az1) * s;
|
|
||||||
deltax = -sin(SG_PI/2+az1) * s;
|
|
||||||
// deltax = cos(0.0) * s;
|
|
||||||
// deltay = sin(0.0) * s;
|
|
||||||
this->alt = alt;
|
this->alt = alt;
|
||||||
|
|
||||||
// simulate clouds movement from wind
|
// simulate clouds movement from wind
|
||||||
@ -126,13 +144,51 @@ void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, doub
|
|||||||
relative_position[SG_Y] += by;
|
relative_position[SG_Y] += by;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( lon != last_lon || lat != last_lat || sp_dist != 0 ) {
|
||||||
|
Point3D start( last_lon, last_lat, 0.0 );
|
||||||
|
Point3D dest( lon, lat, 0.0 );
|
||||||
|
double course = 0.0, dist = 0.0;
|
||||||
|
|
||||||
|
calc_gc_course_dist( dest, start, &course, &dist );
|
||||||
|
// if start and dest are too close together,
|
||||||
|
// calc_gc_course_dist() can return a course of "nan". If
|
||||||
|
// this happens, lets just use the last known good course.
|
||||||
|
// This is a hack, and it would probably be better to make
|
||||||
|
// calc_gc_course_dist() more robust.
|
||||||
|
if ( isnan(course) ) {
|
||||||
|
course = last_course;
|
||||||
|
} else {
|
||||||
|
last_course = course;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate cloud movement due to external forces
|
||||||
|
double ax = 0.0, ay = 0.0;
|
||||||
|
|
||||||
|
if (dist > 0.0) {
|
||||||
|
ax = cos(course) * dist;
|
||||||
|
ay = sin(course) * dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltax += ax;
|
||||||
|
deltay += ay;
|
||||||
|
|
||||||
|
last_lon = lon;
|
||||||
|
last_lat = lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// correct the frustum with the right far plane
|
// correct the frustum with the right far plane
|
||||||
ssgContext *context = ssgGetCurrentContext();
|
ssgContext *context = ssgGetCurrentContext();
|
||||||
frustum = *context->getFrustum();
|
frustum = *context->getFrustum();
|
||||||
frustum.setNearFar(1.0, CloudVis);
|
frustum.setNearFar(1.0, CloudVis);
|
||||||
}
|
}
|
||||||
|
|
||||||
SGCloudField::SGCloudField() {
|
SGCloudField::SGCloudField() :
|
||||||
|
last_density(0.0),
|
||||||
|
deltax(0.0),
|
||||||
|
deltay(0.0),
|
||||||
|
last_course(0.0)
|
||||||
|
{
|
||||||
sgSetVec3( relative_position, 0,0,0);
|
sgSetVec3( relative_position, 0,0,0);
|
||||||
theField.reserve(200);
|
theField.reserve(200);
|
||||||
inViewClouds.reserve(200);
|
inViewClouds.reserve(200);
|
||||||
@ -147,11 +203,43 @@ SGCloudField::~SGCloudField() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// use a table or else we see poping when moving the slider...
|
||||||
|
static int densTable[][10] = {
|
||||||
|
{0,0,0,0,0,0,0,0,0,0},
|
||||||
|
{1,0,0,0,0,0,0,0,0,0},
|
||||||
|
{1,0,0,0,1,0,0,0,0,0},
|
||||||
|
{1,0,0,0,1,0,0,1,0,0}, // 30%
|
||||||
|
{1,0,1,0,1,0,0,1,0,0},
|
||||||
|
{1,0,1,0,1,0,1,1,0,0}, // 50%
|
||||||
|
{1,0,1,0,1,0,1,1,0,1},
|
||||||
|
{1,0,1,1,1,0,1,1,0,1}, // 70%
|
||||||
|
{1,1,1,1,1,0,1,1,0,1},
|
||||||
|
{1,1,1,1,1,0,1,1,1,1}, // 90%
|
||||||
|
{1,1,1,1,1,1,1,1,1,1}
|
||||||
|
};
|
||||||
|
|
||||||
|
// set the visible flag depending on density
|
||||||
|
void SGCloudField::applyDensity(void) {
|
||||||
|
int row = (int) (density / 10.0);
|
||||||
|
int col = 0;
|
||||||
|
list_of_Cloud::iterator iCloud;
|
||||||
|
for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) {
|
||||||
|
if(++col > 9)
|
||||||
|
col = 0;
|
||||||
|
if( densTable[row][col] ) {
|
||||||
|
iCloud->visible = true;
|
||||||
|
} else
|
||||||
|
iCloud->visible = false;
|
||||||
|
}
|
||||||
|
last_density = density;
|
||||||
|
}
|
||||||
|
|
||||||
// add one cloud, data is not copied, ownership given
|
// add one cloud, data is not copied, ownership given
|
||||||
void SGCloudField::addCloud( sgVec3 pos, SGNewCloud *cloud) {
|
void SGCloudField::addCloud( sgVec3 pos, SGNewCloud *cloud) {
|
||||||
Cloud cl;
|
Cloud cl;
|
||||||
sgCopyVec3( cl.pos, pos );
|
sgCopyVec3( cl.pos, pos );
|
||||||
cl.aCloud = cloud;
|
cl.aCloud = cloud;
|
||||||
|
cl.visible = true;
|
||||||
cloud->SetPos( pos );
|
cloud->SetPos( pos );
|
||||||
theField.push_back( cl );
|
theField.push_back( cl );
|
||||||
}
|
}
|
||||||
@ -165,7 +253,7 @@ static float Rnd(float n) {
|
|||||||
// build a field of cloud of size 25x25 km, its a grid of 11x11 clouds
|
// build a field of cloud of size 25x25 km, its a grid of 11x11 clouds
|
||||||
void SGCloudField::buildTestLayer(void) {
|
void SGCloudField::buildTestLayer(void) {
|
||||||
|
|
||||||
const float s = 2200.0f;
|
const float s = 2250.0f;
|
||||||
|
|
||||||
for( int z = -5 ; z <= 5 ; z++) {
|
for( int z = -5 ; z <= 5 ; z++) {
|
||||||
for( int x = -5 ; x <= 5 ; x++ ) {
|
for( int x = -5 ; x <= 5 ; x++ ) {
|
||||||
@ -175,21 +263,23 @@ void SGCloudField::buildTestLayer(void) {
|
|||||||
addCloud(pos, cloud);
|
addCloud(pos, cloud);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
applyDensity();
|
||||||
}
|
}
|
||||||
|
|
||||||
// cull all clouds of a tiled field
|
// cull all clouds of a tiled field
|
||||||
void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) {
|
void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) {
|
||||||
list_of_Cloud::iterator iCloud;
|
list_of_Cloud::iterator iCloud;
|
||||||
// const float distVisCompare = CloudVis * CloudVis;
|
|
||||||
|
|
||||||
// TODO:cull the field before culling the clouds in the field (should eliminate 3 fields)
|
// TODO:cull the field before culling the clouds in the field (should eliminate 3 fields)
|
||||||
for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) {
|
for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) {
|
||||||
sgVec3 dist;
|
sgVec3 dist;
|
||||||
sgSphere sphere;
|
sgSphere sphere;
|
||||||
|
if( ! iCloud->visible )
|
||||||
|
continue;
|
||||||
sgSubVec3( dist, iCloud->pos, eyePos );
|
sgSubVec3( dist, iCloud->pos, eyePos );
|
||||||
sphere.setCenter(dist[0], dist[2], dist[1]);
|
sphere.setCenter(dist[0], dist[2], dist[1]);
|
||||||
sphere.setRadius(iCloud->aCloud->getRadius());
|
float radius = iCloud->aCloud->getRadius();
|
||||||
|
sphere.setRadius(radius);
|
||||||
sphere.orthoXform(mat);
|
sphere.orthoXform(mat);
|
||||||
if( frustum.contains( & sphere ) != SG_OUTSIDE ) {
|
if( frustum.contains( & sphere ) != SG_OUTSIDE ) {
|
||||||
float squareDist = dist[0]*dist[0] + dist[1]*dist[1] + dist[2]*dist[2];
|
float squareDist = dist[0]*dist[0] + dist[1]*dist[1] + dist[2]*dist[2];
|
||||||
@ -199,16 +289,13 @@ void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) {
|
|||||||
// save distance for later sort, opposite distance because we want back to front
|
// save distance for later sort, opposite distance because we want back to front
|
||||||
tmp.dist = - squareDist;
|
tmp.dist = - squareDist;
|
||||||
inViewClouds.push_back(tmp);
|
inViewClouds.push_back(tmp);
|
||||||
|
if( squareDist - radius*radius < 100*100 )
|
||||||
|
sgEnviro.set_view_in_cloud(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void myswap(float &a, float &b) {
|
|
||||||
float tmp = a;
|
|
||||||
a = b;
|
|
||||||
b = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render a cloud field
|
// Render a cloud field
|
||||||
// because no field can have an infinite size (and we don't want to reach his border)
|
// because no field can have an infinite size (and we don't want to reach his border)
|
||||||
@ -221,30 +308,29 @@ void SGCloudField::Render(void) {
|
|||||||
if( ! enable3D )
|
if( ! enable3D )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if( last_density != density ) {
|
||||||
|
last_density = density;
|
||||||
|
applyDensity();
|
||||||
|
}
|
||||||
|
|
||||||
// ask the impostor cache to do some cleanup
|
// ask the impostor cache to do some cleanup
|
||||||
// TODO:don't do that for every field
|
// TODO:don't do that for every field
|
||||||
SGNewCloud::cldCache->startNewFrame();
|
SGNewCloud::cldCache->startNewFrame();
|
||||||
|
|
||||||
inViewClouds.clear();
|
inViewClouds.clear();
|
||||||
|
|
||||||
// cloud fields are tiled on the flat earth
|
|
||||||
// compute the position in the tile
|
|
||||||
relx = -fmod( deltax + relative_position[SG_X], fieldSize );
|
|
||||||
rely = -fmod( deltay + relative_position[SG_Y], fieldSize );
|
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
sgMat4 modelview, tmp, invtrans;
|
sgMat4 modelview, tmp, invtrans;
|
||||||
|
|
||||||
// try to find the sun position (buggy)
|
// try to find the sun position
|
||||||
sgTransposeNegateMat4( invtrans, transform );
|
sgTransposeNegateMat4( invtrans, transform );
|
||||||
sgVec3 lightVec;
|
sgVec3 lightVec;
|
||||||
ssgGetLight( 0 )->getPosition( lightVec );
|
ssgGetLight( 0 )->getPosition( lightVec );
|
||||||
sgNegateVec3( lightVec );
|
|
||||||
sgXformVec3( lightVec, invtrans );
|
sgXformVec3( lightVec, invtrans );
|
||||||
sgNormaliseVec3( lightVec );
|
|
||||||
sgCopyVec3( SGNewCloud::modelSunDir, lightVec );
|
sgCopyVec3( SGNewCloud::modelSunDir, lightVec );
|
||||||
|
sgSetVec3( SGNewCloud::modelSunDir, lightVec[0], lightVec[2], lightVec[1]);
|
||||||
// try to find the lighting data (buggy)
|
// try to find the lighting data (buggy)
|
||||||
sgVec4 diffuse, ambient;
|
sgVec4 diffuse, ambient;
|
||||||
ssgGetLight( 0 )->getColour( GL_DIFFUSE, diffuse );
|
ssgGetLight( 0 )->getColour( GL_DIFFUSE, diffuse );
|
||||||
@ -257,11 +343,12 @@ void SGCloudField::Render(void) {
|
|||||||
sgCopyMat4( tmp, transform );
|
sgCopyMat4( tmp, transform );
|
||||||
sgPostMultMat4( tmp, modelview );
|
sgPostMultMat4( tmp, modelview );
|
||||||
|
|
||||||
sgSetVec3( eyePos, -relx, -tmp[3][2], -rely);
|
// cloud fields are tiled on the flat earth
|
||||||
sgSetVec3( eyePos, -relx, 0, -rely);
|
// compute the position in the tile
|
||||||
|
relx = -fmod( deltax + relative_position[SG_X] + tmp[3][0], fieldSize );
|
||||||
|
rely = -fmod( deltay + relative_position[SG_Y] + tmp[3][1], fieldSize );
|
||||||
|
|
||||||
sgSetVec3( eyePos, -relx, alt, -rely);
|
sgSetVec3( eyePos, -relx, alt, -rely);
|
||||||
// sgSetVec3( eyePos, 0, - tmp[3][2], 0);
|
|
||||||
// sgSetVec3( eyePos, 20000, - tmp[3][2], 20000);
|
|
||||||
|
|
||||||
tmp[3][2] = 0;
|
tmp[3][2] = 0;
|
||||||
tmp[3][0] = 0;
|
tmp[3][0] = 0;
|
||||||
@ -296,12 +383,10 @@ void SGCloudField::Render(void) {
|
|||||||
glEnable(GL_ALPHA_TEST);
|
glEnable(GL_ALPHA_TEST);
|
||||||
glAlphaFunc(GL_GREATER, 0.0f);
|
glAlphaFunc(GL_GREATER, 0.0f);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
// glDisable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_SMOOTH);
|
glEnable(GL_SMOOTH);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||||
// glEnable( GL_COLOR_MATERIAL );
|
|
||||||
glEnable( GL_TEXTURE_2D );
|
glEnable( GL_TEXTURE_2D );
|
||||||
glDisable( GL_FOG );
|
glDisable( GL_FOG );
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
@ -316,11 +401,13 @@ void SGCloudField::Render(void) {
|
|||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||||
|
glEnable( GL_FOG );
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
ssgLoadModelviewMatrix( modelview );
|
ssgLoadModelviewMatrix( modelview );
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
// glEnable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
sgVec3 eyePos;
|
sgVec3 eyePos;
|
||||||
float dist;
|
float dist;
|
||||||
bool operator<(const culledCloud &b) const {
|
bool operator<(const culledCloud &b) const {
|
||||||
return (this->dist < b.dist);
|
return this->dist < b.dist;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
typedef vector<culledCloud> list_of_culledCloud;
|
typedef vector<culledCloud> list_of_culledCloud;
|
||||||
@ -50,6 +50,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
SGNewCloud *aCloud;
|
SGNewCloud *aCloud;
|
||||||
sgVec3 pos;
|
sgVec3 pos;
|
||||||
|
bool visible;
|
||||||
// float dist;
|
// float dist;
|
||||||
// bool culled;
|
// bool culled;
|
||||||
|
|
||||||
@ -64,6 +65,8 @@ private:
|
|||||||
// cull all clouds of a tiled field
|
// cull all clouds of a tiled field
|
||||||
void cullClouds(sgVec3 eyePos, sgMat4 mat);
|
void cullClouds(sgVec3 eyePos, sgMat4 mat);
|
||||||
|
|
||||||
|
void applyDensity(void);
|
||||||
|
|
||||||
list_of_Cloud theField;
|
list_of_Cloud theField;
|
||||||
// this is a relative position only, with that we can move all clouds at once
|
// this is a relative position only, with that we can move all clouds at once
|
||||||
sgVec3 relative_position;
|
sgVec3 relative_position;
|
||||||
@ -73,6 +76,9 @@ private:
|
|||||||
|
|
||||||
sgMat4 transform;
|
sgMat4 transform;
|
||||||
double deltax, deltay, alt;
|
double deltax, deltay, alt;
|
||||||
|
double last_lon, last_lat, last_course;
|
||||||
|
|
||||||
|
float last_density;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -101,11 +107,13 @@ public:
|
|||||||
|
|
||||||
// return the size of the memory pool used by texture impostors
|
// return the size of the memory pool used by texture impostors
|
||||||
static int get_CacheSize(void);
|
static int get_CacheSize(void);
|
||||||
|
static int get_CacheResolution(void);
|
||||||
static float get_CloudVis(void) { return CloudVis; }
|
static float get_CloudVis(void) { return CloudVis; }
|
||||||
static float get_density(void) { return density; }
|
static float get_density(void) { return density; }
|
||||||
static bool get_enable3dClouds(void) { return enable3D; }
|
static bool get_enable3dClouds(void) { return enable3D; }
|
||||||
|
|
||||||
static void set_CacheSize(int sizeKb);
|
static void set_CacheSize(int sizeKb);
|
||||||
|
static void set_CacheResolution(int resolutionPixels);
|
||||||
static void set_CloudVis(float distance);
|
static void set_CloudVis(float distance);
|
||||||
static void set_density(float density);
|
static void set_density(float density);
|
||||||
static void set_enable3dClouds(bool enable);
|
static void set_enable3dClouds(bool enable);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include STL_ALGORITHM
|
#include STL_ALGORITHM
|
||||||
#include SG_GLU_H
|
#include SG_GLU_H
|
||||||
|
|
||||||
|
#include "cloudfield.hxx"
|
||||||
#include "newcloud.hxx"
|
#include "newcloud.hxx"
|
||||||
|
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ static ssgTexture *cloudTextures[SGNewCloud::CLTexture_max];
|
|||||||
bool SGNewCloud::useAnisotropic = true;
|
bool SGNewCloud::useAnisotropic = true;
|
||||||
SGBbCache *SGNewCloud::cldCache = 0;
|
SGBbCache *SGNewCloud::cldCache = 0;
|
||||||
static bool texturesLoaded = false;
|
static bool texturesLoaded = false;
|
||||||
float SGNewCloud::nearRadius = 2500.0f;
|
float SGNewCloud::nearRadius = 3500.0f;
|
||||||
bool SGNewCloud::lowQuality = false;
|
bool SGNewCloud::lowQuality = false;
|
||||||
sgVec3 SGNewCloud::sunlight = {0.5f, 0.5f, 0.5f};
|
sgVec3 SGNewCloud::sunlight = {0.5f, 0.5f, 0.5f};
|
||||||
sgVec3 SGNewCloud::ambLight = {0.5f, 0.5f, 0.5f};
|
sgVec3 SGNewCloud::ambLight = {0.5f, 0.5f, 0.5f};
|
||||||
@ -67,7 +68,7 @@ SGNewCloud::SGNewCloud() :
|
|||||||
// if( ! texturesLoaded ) {}
|
// if( ! texturesLoaded ) {}
|
||||||
if( cldCache == 0 ) {
|
if( cldCache == 0 ) {
|
||||||
cldCache = new SGBbCache;
|
cldCache = new SGBbCache;
|
||||||
cldCache->init( 20 );
|
cldCache->init( 64 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +310,7 @@ void SGNewCloud::genSprites( void ) {
|
|||||||
|
|
||||||
// definition of a cu cloud, only for testing
|
// definition of a cu cloud, only for testing
|
||||||
void SGNewCloud::new_cu(void) {
|
void SGNewCloud::new_cu(void) {
|
||||||
float s = 150.0f;
|
float s = 250.0f;
|
||||||
float r = Rnd(1.0) + 0.5;
|
float r = Rnd(1.0) + 0.5;
|
||||||
if( r < 0.5f ) {
|
if( r < 0.5f ) {
|
||||||
addContainer(0.0f, 0.0f, 0.0f, s, CLbox_cumulus);
|
addContainer(0.0f, 0.0f, 0.0f, s, CLbox_cumulus);
|
||||||
@ -332,7 +333,7 @@ void SGNewCloud::new_cu(void) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// cb
|
// cb
|
||||||
s = 475.0f;
|
s = 675.0f;
|
||||||
addContainer(0, 0, 0, s, CLbox_cumulus);
|
addContainer(0, 0, 0, s, CLbox_cumulus);
|
||||||
addContainer(0, 0, s, s, CLbox_cumulus);
|
addContainer(0, 0, s, s, CLbox_cumulus);
|
||||||
addContainer(s, 0, s, s, CLbox_cumulus);
|
addContainer(s, 0, s, s, CLbox_cumulus);
|
||||||
@ -368,43 +369,12 @@ void SGNewCloud::SetPos(sgVec3 newPos) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Public Sub drawContainers()
|
|
||||||
Dim N As Integer, i As Integer
|
|
||||||
N = UBound(tbSpriteCont())
|
|
||||||
|
|
||||||
Call glPolygonMode(faceFrontAndBack, pgmLine)
|
|
||||||
|
|
||||||
Call glColor3f(0.9, 0.9, 0.9)
|
|
||||||
|
|
||||||
For i = 0 To N - 1
|
|
||||||
With tbSpriteCont(i)
|
|
||||||
Call glPushMatrix
|
|
||||||
Call glTranslatef(.x * c_scale + cloudpos(0), .y * c_scale + cloudpos(1), .z * c_scale + cloudpos(2))
|
|
||||||
Call gCtl.Shapes.box(.r * c_scale, .r * c_scale, .r * c_scale)
|
|
||||||
Call glPopMatrix
|
|
||||||
End With
|
|
||||||
Next i
|
|
||||||
If 0 Then
|
|
||||||
Call glPushMatrix
|
|
||||||
Call glTranslatef(ccenter(0), ccenter(1), ccenter(2))
|
|
||||||
Call gCtl.Shapes.Sphere(cradius, 8, 8)
|
|
||||||
Call glPopMatrix
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
*/
|
|
||||||
void SGNewCloud::drawContainers() {
|
void SGNewCloud::drawContainers() {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
//bool SGNewCloud::compareSpriteFunction(const spriteDef &a, const spriteDef &b) {
|
|
||||||
// return (a.dist > b.dist);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// sort on distance to eye because of transparency
|
// sort on distance to eye because of transparency
|
||||||
void SGNewCloud::sortSprite( sgVec3 eye ) {
|
void SGNewCloud::sortSprite( sgVec3 eye ) {
|
||||||
@ -424,7 +394,12 @@ void SGNewCloud::Render3Dcloud( bool drawBB, sgVec3 FakeEyePos, sgVec3 deltaPos,
|
|||||||
|
|
||||||
/* int clrank = fadingrank / 10;
|
/* int clrank = fadingrank / 10;
|
||||||
int clfadeinrank = fadingrank - clrank * 10;*/
|
int clfadeinrank = fadingrank - clrank * 10;*/
|
||||||
|
float CloudVisFade = 1.0 / (1.5 * SGCloudField::get_CloudVis());
|
||||||
|
|
||||||
|
computeSimpleLight( FakeEyePos );
|
||||||
|
|
||||||
|
// view point sort, we sort because of transparency
|
||||||
|
sortSprite( FakeEyePos );
|
||||||
|
|
||||||
GLint previousTexture = -1, thisTexture;
|
GLint previousTexture = -1, thisTexture;
|
||||||
list_of_spriteDef::iterator iSprite;
|
list_of_spriteDef::iterator iSprite;
|
||||||
@ -491,8 +466,7 @@ void SGNewCloud::Render3Dcloud( bool drawBB, sgVec3 FakeEyePos, sgVec3 deltaPos,
|
|||||||
sgCopyVec4 ( l3, iSprite->l3 );
|
sgCopyVec4 ( l3, iSprite->l3 );
|
||||||
if( ! drawBB ) {
|
if( ! drawBB ) {
|
||||||
// blend clouds with sky based on distance to limit the contrast of distant cloud
|
// blend clouds with sky based on distance to limit the contrast of distant cloud
|
||||||
// TODO:use cloudfield vis, not hardcoded value
|
float t = 1.0f - dist_center * CloudVisFade;
|
||||||
float t = 1.0f - dist_center / (15000.0f * 2.0 );
|
|
||||||
if ( t < 0.0f )
|
if ( t < 0.0f )
|
||||||
t = 0.0f; // no, it should have been culled
|
t = 0.0f; // no, it should have been culled
|
||||||
// now clouds at the far plane are half blended
|
// now clouds at the far plane are half blended
|
||||||
@ -591,8 +565,9 @@ void SGNewCloud::RenderBB(sgVec3 deltaPos, float angleY, float angleX, float dis
|
|||||||
glRotatef(angleX, 1.0f, 0.0f, 0.0f);
|
glRotatef(angleX, 1.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
// blend clouds with sky based on distance to limit the contrast of distant cloud
|
// blend clouds with sky based on distance to limit the contrast of distant cloud
|
||||||
// TODO:use cloudfield vis, not hardcoded value
|
float CloudVisFade = (1.5 * SGCloudField::get_CloudVis());
|
||||||
float t = 1.0f - dist_center / (15000.0f * 2.0 );
|
|
||||||
|
float t = 1.0f - dist_center / CloudVisFade;
|
||||||
// err the alpha value is not good for impostor, debug that
|
// err the alpha value is not good for impostor, debug that
|
||||||
t *= 1.65;
|
t *= 1.65;
|
||||||
if ( t < 0.0f )
|
if ( t < 0.0f )
|
||||||
@ -611,7 +586,7 @@ void SGNewCloud::RenderBB(sgVec3 deltaPos, float angleY, float angleX, float dis
|
|||||||
glVertex2f(-r, -r);
|
glVertex2f(-r, -r);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
#if 1 // debug only
|
#if 0 // debug only
|
||||||
int age = cldCache->queryImpostorAge(bbId);
|
int age = cldCache->queryImpostorAge(bbId);
|
||||||
// draw a red border for the newly generated BBs else draw a white border
|
// draw a red border for the newly generated BBs else draw a white border
|
||||||
if( age < 200 )
|
if( age < 200 )
|
||||||
@ -646,36 +621,21 @@ bool SGNewCloud::isBillboardable(float dist) {
|
|||||||
// near clouds we don't want to use BB
|
// near clouds we don't want to use BB
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// render the cloud, fakepos is a relative position inside the cloud field
|
// render the cloud, fakepos is a relative position inside the cloud field
|
||||||
void SGNewCloud::Render(sgVec3 fakepos) {
|
void SGNewCloud::Render(sgVec3 FakeEyePos) {
|
||||||
sgVec3 eyePos, FakeEyePos;
|
|
||||||
sgVec3 dist;
|
sgVec3 dist;
|
||||||
|
|
||||||
|
|
||||||
glColor3f(1.0f, 1.0f, 1.0f);
|
|
||||||
|
|
||||||
// obsolete code
|
|
||||||
sgCopyVec3( eyePos, fakepos );
|
|
||||||
|
|
||||||
sgCopyVec3( FakeEyePos, fakepos);
|
|
||||||
sgVec3 deltaPos;
|
sgVec3 deltaPos;
|
||||||
// sgSubVec3( deltaPos, eyePos, FakeEyePos);
|
|
||||||
sgCopyVec3( deltaPos, FakeEyePos);
|
sgCopyVec3( deltaPos, FakeEyePos);
|
||||||
sgSubVec3( dist, center, FakeEyePos);
|
sgSubVec3( dist, center, FakeEyePos);
|
||||||
float dist_center = sgLengthVec3(dist);
|
float dist_center = sgLengthVec3(dist);
|
||||||
|
|
||||||
// eeeek don't do that so early, perhaps we will use an impostor
|
|
||||||
computeSimpleLight( FakeEyePos );
|
|
||||||
|
|
||||||
// view point sort, we sort because of transparency
|
|
||||||
// eeeek don't do that so early, perhaps we will use an impostor
|
|
||||||
sortSprite( FakeEyePos );
|
|
||||||
|
|
||||||
|
|
||||||
if( !isBillboardable(dist_center) ) {
|
if( !isBillboardable(dist_center) ) {
|
||||||
|
Loading…
Reference in New Issue
Block a user