3D clouds from Stuart Buchanan. Need a recent driver update, --enable-clouds3d option and a Weather Scenario to show up
This commit is contained in:
@@ -508,6 +508,12 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\sky\cloudfield.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\sky\CloudShaderGeometry.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\sky\CloudShaderGeometry.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\sky\dome.cxx">
|
||||
</File>
|
||||
|
||||
@@ -203,8 +203,6 @@ void SGEnviro::startOfFrame( sgVec3 p, sgVec3 up, double lon, double lat, double
|
||||
return;
|
||||
view_in_cloud = false;
|
||||
// ask the impostor cache to do some cleanup
|
||||
if(SGNewCloud::cldCache)
|
||||
SGNewCloud::cldCache->startNewFrame();
|
||||
last_cloud_turbulence = cloud_turbulence;
|
||||
cloud_turbulence = 0.0;
|
||||
elapsed_time += delta_time;
|
||||
@@ -255,43 +253,10 @@ 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 {
|
||||
return SGCloudField::get_CacheSize();
|
||||
}
|
||||
float SGEnviro::get_clouds_visibility(void) const {
|
||||
return SGCloudField::get_CloudVis();
|
||||
}
|
||||
float SGEnviro::get_clouds_density(void) const {
|
||||
return SGCloudField::get_density();
|
||||
}
|
||||
bool SGEnviro::get_clouds_enable_state(void) const {
|
||||
return SGCloudField::get_enable3dClouds();
|
||||
}
|
||||
|
||||
bool SGEnviro::get_turbulence_enable_state(void) const {
|
||||
return turbulence_enable_state;
|
||||
}
|
||||
|
||||
void SGEnviro::set_CacheResolution(int resolutionPixels) {
|
||||
SGCloudField::set_CacheResolution(resolutionPixels);
|
||||
}
|
||||
|
||||
void SGEnviro::set_clouds_CacheSize(int sizeKb) {
|
||||
SGCloudField::set_CacheSize(sizeKb);
|
||||
}
|
||||
void SGEnviro::set_clouds_visibility(float distance) {
|
||||
SGCloudField::set_CloudVis(distance);
|
||||
}
|
||||
void SGEnviro::set_clouds_density(float density) {
|
||||
SGCloudField::set_density(density);
|
||||
}
|
||||
void SGEnviro::set_clouds_enable_state(bool enable) {
|
||||
SGCloudField::set_enable3dClouds(enable);
|
||||
}
|
||||
void SGEnviro::set_turbulence_enable_state(bool enable) {
|
||||
turbulence_enable_state = enable;
|
||||
}
|
||||
@@ -330,7 +295,7 @@ void SGEnviro::setLight(sgVec4 adj_fog_color) {
|
||||
// ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SGEnviro::callback_cloud(float heading, float alt, float radius, int family, float dist, int cloudId) {
|
||||
// send data to wx radar
|
||||
// compute turbulence
|
||||
@@ -441,6 +406,8 @@ void SGEnviro::callback_cloud(float heading, float alt, float radius, int family
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
list_of_SGWxRadarEcho *SGEnviro::get_radar_echo(void) {
|
||||
return &radarEcho;
|
||||
}
|
||||
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
|
||||
void endOfFrame(void);
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Whenever a cloud is drawn we check his 'impact' on the environment.
|
||||
* @param heading direction of cloud in radians
|
||||
@@ -134,7 +135,7 @@ public:
|
||||
* @param dist squared dist to cloud in meters
|
||||
*/
|
||||
void callback_cloud(float heading, float alt, float radius, int family, float dist, int cloudId);
|
||||
|
||||
#endif
|
||||
void drawRain(double pitch, double roll, double heading, double hspeed, double rain_norm);
|
||||
/**
|
||||
* Draw rain or snow precipitation around the viewer.
|
||||
|
||||
139
simgear/scene/sky/CloudShaderGeometry.cxx
Executable file
139
simgear/scene/sky/CloudShaderGeometry.cxx
Executable file
@@ -0,0 +1,139 @@
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2008 Stuart Buchanan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/ParameterOutput>
|
||||
|
||||
#include "CloudShaderGeometry.hxx"
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgDB;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
|
||||
{
|
||||
osg::State& state = *renderInfo.getState();
|
||||
const Extensions* extensions = getExtensions(state.getContextID(),true);
|
||||
|
||||
for(CloudSpriteList::const_iterator t = _cloudsprites.begin(); t != _cloudsprites.end(); ++t)
|
||||
{
|
||||
extensions->glVertexAttrib1f(TEXTURE_INDEX_X, (GLfloat) t->texture_index_x/varieties_x);
|
||||
extensions->glVertexAttrib1f(TEXTURE_INDEX_Y, (GLfloat) t->texture_index_y/varieties_y);
|
||||
extensions->glVertexAttrib1f(WIDTH, (GLfloat) t->width);
|
||||
extensions->glVertexAttrib1f(HEIGHT, (GLfloat) t->height);
|
||||
extensions->glVertexAttrib1f(SHADE, (GLfloat) t->shade);
|
||||
glColor4f(t->position.x(), t->position.y(), t->position.z(), 1.0);
|
||||
_geometry->draw(renderInfo);
|
||||
}
|
||||
}
|
||||
|
||||
BoundingBox CloudShaderGeometry::computeBound() const
|
||||
{
|
||||
BoundingBox geom_box = _geometry->getBound();
|
||||
BoundingBox bb;
|
||||
for(CloudSpriteList::const_iterator itr = _cloudsprites.begin();
|
||||
itr != _cloudsprites.end();
|
||||
++itr) {
|
||||
bb.expandBy(geom_box.corner(0)*itr->width +
|
||||
osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() ));
|
||||
bb.expandBy(geom_box.corner(7)*itr->height +
|
||||
osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() ));
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
|
||||
CloudShaderGeometry& geom = static_cast<CloudShaderGeometry&>(obj);
|
||||
|
||||
if ((fr[0].matchWord("geometry"))) {
|
||||
++fr;
|
||||
iteratorAdvanced = true;
|
||||
osg::Drawable* drawable = fr.readDrawable();
|
||||
if (drawable) {
|
||||
geom._geometry = drawable;
|
||||
}
|
||||
}
|
||||
if ((fr.matchSequence("instances %i"))) {
|
||||
int entry = fr[0].getNoNestedBrackets();
|
||||
int capacity;
|
||||
fr[1].getInt(capacity);
|
||||
geom._cloudsprites.reserve(capacity);
|
||||
fr += 3;
|
||||
iteratorAdvanced = true;
|
||||
// skip {
|
||||
while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
|
||||
SGVec3f v;
|
||||
int tx, ty;
|
||||
float w, h, s;
|
||||
if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
|
||||
&& fr[2].getFloat(v.z()) && fr[3].getInt(tx) && fr[3].getInt(ty) &&
|
||||
fr[4].getFloat(w) && fr[4].getFloat(h)&& fr[4].getFloat(s)) {
|
||||
fr += 5;
|
||||
//SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
|
||||
geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h,s));
|
||||
} else {
|
||||
++fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool CloudShaderGeometry_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
const CloudShaderGeometry& geom = static_cast<const CloudShaderGeometry&>(obj);
|
||||
|
||||
fw.indent() << "geometry" << std::endl;
|
||||
fw.writeObject(*geom._geometry);
|
||||
fw.indent() << "instances " << geom._cloudsprites.size() << std::endl;
|
||||
fw.indent() << "{" << std::endl;
|
||||
fw.moveIn();
|
||||
for (CloudShaderGeometry::CloudSpriteList::const_iterator iter
|
||||
= geom._cloudsprites.begin();
|
||||
iter != geom._cloudsprites.end();
|
||||
++iter) {
|
||||
fw.indent() << iter->position.x() << " " << iter->position.y() << " "
|
||||
<< iter->position.z() << " " << iter->texture_index_x << " "
|
||||
<< iter->texture_index_y << " "
|
||||
<< iter->width << " " << iter->height << " " << iter->shade << std::endl;
|
||||
}
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy cloudShaderGeometryProxy
|
||||
(
|
||||
new CloudShaderGeometry,
|
||||
"CloudShaderGeometry",
|
||||
"Object Drawable CloudShaderGeometry",
|
||||
&CloudShaderGeometry_readLocalData,
|
||||
&CloudShaderGeometry_writeLocalData
|
||||
);
|
||||
}
|
||||
134
simgear/scene/sky/CloudShaderGeometry.hxx
Executable file
134
simgear/scene/sky/CloudShaderGeometry.hxx
Executable file
@@ -0,0 +1,134 @@
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2008 Stuart Buchanan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CLOUD_SHADER_GEOMETRY_HXX
|
||||
#define CLOUD_SHADER_GEOMETRY_HXX 1
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <osg/BoundingBox>
|
||||
#include <osg/CopyOp>
|
||||
#include <osg/Drawable>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/RenderInfo>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
class CloudShaderGeometry : public osg::Drawable
|
||||
{
|
||||
public:
|
||||
|
||||
const static unsigned int TEXTURE_INDEX_X = 11;
|
||||
const static unsigned int TEXTURE_INDEX_Y = 12;
|
||||
const static unsigned int WIDTH = 13;
|
||||
const static unsigned int HEIGHT = 14;
|
||||
const static unsigned int SHADE = 15;
|
||||
|
||||
CloudShaderGeometry()
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
}
|
||||
|
||||
CloudShaderGeometry(int vx, int vy) :
|
||||
varieties_x(vx), varieties_y(vy)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
}
|
||||
|
||||
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
||||
CloudShaderGeometry(const CloudShaderGeometry& CloudShaderGeometry,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
|
||||
osg::Drawable(CloudShaderGeometry,copyop) {}
|
||||
|
||||
META_Object(flightgear, CloudShaderGeometry);
|
||||
|
||||
struct CloudSprite {
|
||||
CloudSprite(const SGVec3f& p, int tx, int ty, float w, float h, float s) :
|
||||
position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h), shade(s)
|
||||
{ }
|
||||
|
||||
SGVec3f position;
|
||||
int texture_index_x;
|
||||
int texture_index_y;
|
||||
float width;
|
||||
float height;
|
||||
float shade;
|
||||
};
|
||||
|
||||
typedef std::vector<CloudSprite> CloudSpriteList;
|
||||
|
||||
void insert(const CloudSprite& t)
|
||||
{ _cloudsprites.push_back(t); }
|
||||
void insert(const SGVec3f& p, int tx, int ty, float w, float h, float s)
|
||||
{ insert(CloudSprite(p, tx, ty, w, h, s)); }
|
||||
|
||||
unsigned getNumCloudSprite() const
|
||||
{ return _cloudsprites.size(); }
|
||||
const CloudSprite& getCloudSprite(unsigned i) const
|
||||
{ return _cloudsprites[i]; }
|
||||
CloudSpriteList _cloudsprites;
|
||||
|
||||
typedef std::vector<osg::Vec4> PositionSizeList;
|
||||
|
||||
virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
|
||||
virtual osg::BoundingBox computeBound() const;
|
||||
|
||||
|
||||
void setGeometry(osg::Drawable* geometry)
|
||||
{
|
||||
_geometry = geometry;
|
||||
}
|
||||
|
||||
void addSprite(const SGVec3f& p, int tx, int ty, float w, float h, float s, float cull)
|
||||
{
|
||||
// Only add the sprite if it is further than the cull distance to all other sprites
|
||||
for (CloudShaderGeometry::CloudSpriteList::const_iterator iter = _cloudsprites.begin();
|
||||
iter != _cloudsprites.end();
|
||||
++iter)
|
||||
{
|
||||
if (distSqr(iter->position, p) < cull)
|
||||
{
|
||||
// Too close - cull it
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_cloudsprites.push_back(CloudSprite(p, tx, ty, w, h, s));
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Drawable> _geometry;
|
||||
|
||||
int varieties_x;
|
||||
int varieties_y;
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~CloudShaderGeometry() {}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -12,7 +12,8 @@ include_HEADERS = \
|
||||
stars.hxx \
|
||||
bbcache.hxx \
|
||||
cloudfield.hxx \
|
||||
newcloud.hxx
|
||||
newcloud.hxx \
|
||||
CloudShaderGeometry.hxx
|
||||
|
||||
libsgsky_a_SOURCES = \
|
||||
cloud.cxx \
|
||||
@@ -24,6 +25,7 @@ libsgsky_a_SOURCES = \
|
||||
stars.cxx \
|
||||
bbcache.cxx \
|
||||
cloudfield.cxx \
|
||||
newcloud.cxx
|
||||
newcloud.cxx \
|
||||
CloudShaderGeometry.cxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TextureCubeMap>
|
||||
#include <osg/TexMat>
|
||||
#include <osg/Fog>
|
||||
|
||||
#include <simgear/math/sg_random.h>
|
||||
#include <simgear/misc/PathOptions.hxx>
|
||||
@@ -127,6 +128,7 @@ SGMakeState(const SGPath &path, const char* colorTexture,
|
||||
|
||||
// Constructor
|
||||
SGCloudLayer::SGCloudLayer( const string &tex_path ) :
|
||||
cloud_root(new osg::Switch),
|
||||
layer_root(new osg::Switch),
|
||||
group_top(new osg::Group),
|
||||
group_bottom(new osg::Group),
|
||||
@@ -149,6 +151,7 @@ SGCloudLayer::SGCloudLayer( const string &tex_path ) :
|
||||
// in bin 10), tops after. The negative numbers on the bottoms
|
||||
// RenderBins and the positive numbers on the tops enforce this
|
||||
// order.
|
||||
cloud_root->addChild(layer_root.get(), true);
|
||||
layer_root->addChild(group_bottom.get());
|
||||
layer_root->addChild(group_top.get());
|
||||
osg::StateSet *rootSet = layer_root->getOrCreateStateSet();
|
||||
@@ -192,7 +195,9 @@ SGCloudLayer::SGCloudLayer( const string &tex_path ) :
|
||||
group_top->addChild(layer_transform.get());
|
||||
group_bottom->addChild(layer_transform.get());
|
||||
|
||||
layer3D = new SGCloudField;
|
||||
layer3D = new SGCloudField();
|
||||
cloud_root->addChild(layer3D->getNode(), false);
|
||||
|
||||
rebuild();
|
||||
}
|
||||
|
||||
@@ -452,10 +457,6 @@ SGCloudLayer::rebuild()
|
||||
|
||||
layer_states[SG_CLOUD_CLEAR] = 0;
|
||||
layer_states2[SG_CLOUD_CLEAR] = 0;
|
||||
|
||||
// OSGFIXME
|
||||
// SGNewCloud::loadTextures(texture_path.str());
|
||||
// layer3D->buildTestLayer();
|
||||
}
|
||||
|
||||
scale = 4000.0;
|
||||
@@ -560,259 +561,6 @@ SGCloudLayer::rebuild()
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
sgMat4 modelview,
|
||||
tmp,
|
||||
transform;
|
||||
ssgGetModelviewMatrix( modelview );
|
||||
layer_transform->getTransform( transform );
|
||||
|
||||
sgTransposeNegateMat4( tmp, transform );
|
||||
|
||||
sgPostMultMat4( transform, modelview );
|
||||
ssgLoadModelviewMatrix( transform );
|
||||
|
||||
sgVec3 lightVec;
|
||||
ssgGetLight( 0 )->getPosition( lightVec );
|
||||
sgNegateVec3( lightVec );
|
||||
sgXformVec3( lightVec, tmp );
|
||||
|
||||
for ( int i = 0; i < 25; i++ ) {
|
||||
CloudVertex &v = vertices[ i ];
|
||||
sgSetVec3( v.tangentSpLight,
|
||||
sgScalarProductVec3( v.sTangent, lightVec ),
|
||||
sgScalarProductVec3( v.tTangent, lightVec ),
|
||||
sgScalarProductVec3( v.normal, lightVec ) );
|
||||
}
|
||||
|
||||
ssgTexture *decal = color_map[ layer_coverage ][ top ? 1 : 0 ];
|
||||
if ( top && decal == 0 ) {
|
||||
decal = color_map[ layer_coverage ][ 0 ];
|
||||
}
|
||||
ssgTexture *normal = normal_map[ layer_coverage ][ top ? 1 : 0 ];
|
||||
if ( top && normal == 0 ) {
|
||||
normal = normal_map[ layer_coverage ][ 0 ];
|
||||
}
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_CULL_FACE );
|
||||
// glDisable( GL_ALPHA_TEST );
|
||||
if ( layer_coverage == SG_CLOUD_FEW ) {
|
||||
glEnable( GL_ALPHA_TEST );
|
||||
glAlphaFunc ( GL_GREATER, 0.01 );
|
||||
}
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
sgVec4 color;
|
||||
float emis = 0.05;
|
||||
if ( 1 ) {
|
||||
ssgGetLight( 0 )->getColour( GL_DIFFUSE, color );
|
||||
emis = ( color[0]+color[1]+color[2] ) / 3.0;
|
||||
if ( emis < 0.05 )
|
||||
emis = 0.05;
|
||||
}
|
||||
sgSetVec4( color, emis, emis, emis, 0.0 );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, color );
|
||||
sgSetVec4( color, 1.0f, 1.0f, 1.0f, 0.0 );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, color );
|
||||
sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, color );
|
||||
sgSetVec4( color, 0.0, 0.0, 0.0, 0.0 );
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, color );
|
||||
|
||||
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
glActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
glBindTexture( GL_TEXTURE_2D, normal->getHandle() );
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
|
||||
//Bind normalisation cube map to texture unit 1
|
||||
glActiveTexturePtr( GL_TEXTURE1_ARB );
|
||||
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, normalization_cube_map );
|
||||
glEnable( GL_TEXTURE_CUBE_MAP_ARB );
|
||||
glActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
|
||||
//Set vertex arrays for cloud
|
||||
glVertexPointer( 3, GL_FLOAT, sizeof(CloudVertex), &vertices[0].position );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
/*
|
||||
if ( nb_texture_unit >= 3 ) {
|
||||
glColorPointer( 4, GL_FLOAT, sizeof(CloudVertex), &vertices[0].color );
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
}
|
||||
*/
|
||||
//Send texture coords for normal map to unit 0
|
||||
glTexCoordPointer( 2, GL_FLOAT, sizeof(CloudVertex), &vertices[0].texCoord );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
//Send tangent space light vectors for normalisation to unit 1
|
||||
glClientActiveTexturePtr( GL_TEXTURE1_ARB );
|
||||
glTexCoordPointer( 3, GL_FLOAT, sizeof(CloudVertex), &vertices[0].tangentSpLight );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
//Set up texture environment to do (tex0 dot tex1)*color
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE );
|
||||
|
||||
// use TexEnvCombine to add the highlights to the original lighting
|
||||
osg::TexEnvCombine *te = new osg::TexEnvCombine;
|
||||
te->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
|
||||
te->setCombine_RGB(osg::TexEnvCombine::REPLACE);
|
||||
te->setSource0_Alpha(osg::TexEnvCombine::TEXTURE);
|
||||
te->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
|
||||
ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
|
||||
|
||||
|
||||
glActiveTexturePtr( GL_TEXTURE1_ARB );
|
||||
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE );
|
||||
|
||||
osg::TexEnvCombine *te = new osg::TexEnvCombine;
|
||||
te->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
|
||||
te->setCombine_RGB(osg::TexEnvCombine::DOT3_RGB);
|
||||
te->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
|
||||
te->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
|
||||
te->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
|
||||
ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
|
||||
|
||||
|
||||
if ( nb_texture_unit >= 3 ) {
|
||||
glActiveTexturePtr( GL_TEXTURE2_ARB );
|
||||
glBindTexture( GL_TEXTURE_2D, decal->getHandle() );
|
||||
|
||||
glClientActiveTexturePtr( GL_TEXTURE2_ARB );
|
||||
glTexCoordPointer( 2, GL_FLOAT, sizeof(CloudVertex), &vertices[0].texCoord );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
|
||||
|
||||
glClientActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
glActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
|
||||
//Draw cloud layer
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[0] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[10] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[20] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[30] );
|
||||
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
glActiveTexturePtr( GL_TEXTURE1_ARB );
|
||||
glDisable( GL_TEXTURE_CUBE_MAP_ARB );
|
||||
glActiveTexturePtr( GL_TEXTURE2_ARB );
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
glActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glClientActiveTexturePtr( GL_TEXTURE1_ARB );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glClientActiveTexturePtr( GL_TEXTURE2_ARB );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glClientActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glEnable( GL_LIGHTING );
|
||||
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
} else {
|
||||
glClientActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
glActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
|
||||
//Draw cloud layer
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[0] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[10] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[20] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[30] );
|
||||
|
||||
//Disable textures
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
|
||||
glActiveTexturePtr( GL_TEXTURE1_ARB );
|
||||
glDisable( GL_TEXTURE_CUBE_MAP_ARB );
|
||||
glActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
|
||||
//disable vertex arrays
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glClientActiveTexturePtr( GL_TEXTURE1_ARB );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glClientActiveTexturePtr( GL_TEXTURE0_ARB );
|
||||
|
||||
//Return to standard modulate texenv
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
if ( layer_coverage == SG_CLOUD_OVERCAST ) {
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
glEnable( GL_LIGHTING );
|
||||
sgVec4 color;
|
||||
ssgGetLight( 0 )->getColour( GL_DIFFUSE, color );
|
||||
float average = ( color[0] + color[1] + color[2] ) / 3.0f;
|
||||
average = 0.15 + average/10;
|
||||
sgVec4 averageColor;
|
||||
sgSetVec4( averageColor, average, average, average, 1.0f );
|
||||
ssgGetLight( 0 )->setColour( GL_DIFFUSE, averageColor );
|
||||
|
||||
glBlendColorPtr( average, average, average, 1.0f );
|
||||
glBlendFunc( GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR );
|
||||
|
||||
//Perform a second pass to color the torus
|
||||
//Bind decal texture
|
||||
glBindTexture( GL_TEXTURE_2D, decal->getHandle() );
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
//Set vertex arrays for torus
|
||||
glVertexPointer( 3, GL_FLOAT, sizeof(CloudVertex), &vertices[0].position );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
//glColorPointer( 4, GL_FLOAT, sizeof(CloudVertex), &vertices[0].color );
|
||||
//glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
glNormalPointer( GL_FLOAT, sizeof(CloudVertex), &vertices[0].normal );
|
||||
glEnableClientState( GL_NORMAL_ARRAY );
|
||||
|
||||
glTexCoordPointer( 2, GL_FLOAT, sizeof(CloudVertex), &vertices[0].texCoord );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
//Draw cloud layer
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[0] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[10] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[20] );
|
||||
glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, &indices[30] );
|
||||
|
||||
ssgGetLight( 0 )->setColour( GL_DIFFUSE, color );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
}
|
||||
}
|
||||
//Disable texture
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
ssgLoadModelviewMatrix( modelview );
|
||||
#endif
|
||||
|
||||
// repaint the cloud layer colors
|
||||
bool SGCloudLayer::repaint( const SGVec3f& fog_color ) {
|
||||
osg::Vec4f combineColor(fog_color.osg(), cloud_alpha);
|
||||
@@ -820,6 +568,9 @@ bool SGCloudLayer::repaint( const SGVec3f& fog_color ) {
|
||||
= dynamic_cast<osg::TexEnvCombine*>(layer_root->getStateSet()
|
||||
->getTextureAttribute(1, osg::StateAttribute::TEXENV));
|
||||
combiner->setConstantColor(combineColor);
|
||||
|
||||
// Set the fog color for the 3D clouds too.
|
||||
//cloud3dfog->setColor(combineColor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -865,6 +616,7 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
|
||||
LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
|
||||
|
||||
layer_transform->setMatrix( LAT*LON*T );
|
||||
|
||||
// The layers need to be drawn in order because they are
|
||||
// translucent, but OSG transparency sorting doesn't work because
|
||||
// the cloud polys are huge. However, the ordering is simple: the
|
||||
@@ -967,6 +719,21 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
|
||||
last_lat = lat;
|
||||
}
|
||||
|
||||
// layer3D->reposition( p, up, lon, lat, alt, dt, direction, speed);
|
||||
layer3D->reposition( p, up, lon, lat, dt);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SGCloudLayer::set_enable3dClouds(bool enable) {
|
||||
|
||||
if (layer3D->defined3D && enable) {
|
||||
cloud_root->setChildValue(layer3D->getNode(), true);
|
||||
cloud_root->setChildValue(layer_root.get(), false);
|
||||
} else {
|
||||
cloud_root->setChildValue(layer3D->getNode(), false);
|
||||
cloud_root->setChildValue(layer_root.get(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void SGCloudLayer::applyDensity() {
|
||||
layer3D->applyDensity();
|
||||
}
|
||||
|
||||
@@ -162,6 +162,12 @@ public:
|
||||
/** build the cloud object */
|
||||
void rebuild();
|
||||
|
||||
/** Enable/disable 3D clouds in this layer */
|
||||
void set_enable3dClouds(bool enable);
|
||||
|
||||
/** Set 3D cloud density in this layer */
|
||||
void applyDensity();
|
||||
|
||||
/**
|
||||
* repaint the cloud colors based on the specified fog_color
|
||||
* @param fog_color the fog color
|
||||
@@ -183,16 +189,18 @@ public:
|
||||
double lon, double lat, double alt,
|
||||
double dt = 0.0 );
|
||||
|
||||
osg::Switch* getNode() { return layer_root.get(); }
|
||||
osg::Switch* getNode() { return cloud_root.get(); }
|
||||
|
||||
static bool enable_bump_mapping;
|
||||
|
||||
/** return the 3D layer cloud associated with this 2D layer */
|
||||
SGCloudField *get_layer3D(void) { return layer3D; }
|
||||
|
||||
protected:
|
||||
void setTextureOffset(const osg::Vec2& offset);
|
||||
private:
|
||||
|
||||
osg::ref_ptr<osg::Switch> cloud_root;
|
||||
osg::ref_ptr<osg::Switch> layer_root;
|
||||
osg::ref_ptr<osg::Group> group_top, group_bottom;
|
||||
osg::ref_ptr<osg::MatrixTransform> layer_transform;
|
||||
@@ -225,6 +233,7 @@ private:
|
||||
osg::Vec2 base;
|
||||
|
||||
SGCloudField *layer3D;
|
||||
|
||||
};
|
||||
|
||||
#endif // _SG_CLOUD_HXX_
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <plib/sg.h>
|
||||
@@ -58,216 +61,118 @@ using std::vector;
|
||||
#include <ieeefp.h>
|
||||
#endif
|
||||
|
||||
static list_of_culledCloud inViewClouds;
|
||||
|
||||
// visibility distance for clouds in meters
|
||||
float SGCloudField::CloudVis = 25000.0f;
|
||||
bool SGCloudField::enable3D = false;
|
||||
// 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
|
||||
double SGCloudField::fieldSize = 50000.0;
|
||||
float SGCloudField::density = 100.0;
|
||||
double SGCloudField::timer_dt = 0.0;
|
||||
sgVec3 SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;
|
||||
|
||||
static int last_cache_size = 1*1024;
|
||||
static int cacheResolution = 64;
|
||||
static sgVec3 last_sunlight={0.0f, 0.0f, 0.0f};
|
||||
|
||||
int SGCloudField::get_CacheResolution(void) {
|
||||
#if 0
|
||||
return cacheResolution;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SGCloudField::set_CacheResolution(int resolutionPixels) {
|
||||
#if 0
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int SGCloudField::get_CacheSize(void) {
|
||||
#if 0
|
||||
return SGNewCloud::cldCache->queryCacheSize();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SGCloudField::set_CacheSize(int sizeKb) {
|
||||
#if 0
|
||||
// apply in rendering option dialog
|
||||
if(last_cache_size == sizeKb)
|
||||
return;
|
||||
if(sizeKb == 0)
|
||||
return;
|
||||
if(sizeKb)
|
||||
last_cache_size = sizeKb;
|
||||
if(enable3D) {
|
||||
int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4);
|
||||
if(count == 0)
|
||||
count = 1;
|
||||
SGNewCloud::cldCache->setCacheSize(count, cacheResolution);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void SGCloudField::set_CloudVis(float distance) {
|
||||
#if 0
|
||||
if( distance <= fieldSize )
|
||||
SGCloudField::CloudVis = distance;
|
||||
#endif
|
||||
}
|
||||
void SGCloudField::set_density(float density) {
|
||||
#if 0
|
||||
SGCloudField::density = density;
|
||||
#endif
|
||||
}
|
||||
void SGCloudField::set_enable3dClouds(bool enable) {
|
||||
#if 0
|
||||
if(enable3D == enable)
|
||||
return;
|
||||
enable3D = enable;
|
||||
if(enable) {
|
||||
int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4);
|
||||
if(count == 0)
|
||||
count = 1;
|
||||
SGNewCloud::cldCache->setCacheSize(count, cacheResolution);
|
||||
} else {
|
||||
SGNewCloud::cldCache->setCacheSize(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// reposition the cloud layer at the specified origin and orientation
|
||||
void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double dt, float direction, float speed) {
|
||||
#if 0
|
||||
sgMat4 T1, LON, LAT;
|
||||
sgVec3 axis;
|
||||
bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
|
||||
double dt )
|
||||
{
|
||||
osg::Matrix T, LON, LAT;
|
||||
|
||||
sgMakeTransMat4( T1, p );
|
||||
LON.makeRotate(lon, osg::Vec3(0, 0, 1));
|
||||
LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
|
||||
|
||||
sgSetVec3( axis, 0.0, 0.0, 1.0 );
|
||||
sgMakeRotMat4( LON, lon * SGD_RADIANS_TO_DEGREES, axis );
|
||||
osg::Vec3 u = up.osg();
|
||||
u.normalize();
|
||||
|
||||
sgSetVec3( axis, 0.0, 1.0, 0.0 );
|
||||
sgMakeRotMat4( LAT, 90.0 - lat * SGD_RADIANS_TO_DEGREES, axis );
|
||||
if ((last_lon == 0.0f) || (fabs(last_lon - lon) > 1.0) || (fabs(last_lat - lat) > 1.0))
|
||||
{
|
||||
// First time, or large delta requires repositioning from scratch.
|
||||
// TODO: Make this calculation better - a 0.5 degree shift will take a number
|
||||
// of reposition calls to correct at the moment.
|
||||
|
||||
// combine p and asl (meters) to get translation offset.
|
||||
osg::Vec3 pos = p.osg();
|
||||
pos += u;
|
||||
|
||||
T.makeTranslate(pos);
|
||||
|
||||
sgMat4 TRANSFORM;
|
||||
|
||||
sgCopyMat4( TRANSFORM, T1 );
|
||||
sgPreMultMat4( TRANSFORM, LON );
|
||||
sgPreMultMat4( TRANSFORM, LAT );
|
||||
|
||||
sgCoord layerpos;
|
||||
sgSetCoord( &layerpos, TRANSFORM );
|
||||
|
||||
sgMakeCoordMat4( transform, &layerpos );
|
||||
|
||||
|
||||
this->alt = alt;
|
||||
|
||||
// simulate clouds movement from wind
|
||||
double sp_dist = speed*dt;
|
||||
if (sp_dist > 0) {
|
||||
double bx = cos((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
|
||||
double by = sin((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
|
||||
relative_position[SG_X] += bx;
|
||||
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;
|
||||
field_transform->setMatrix( LAT*LON*T );
|
||||
last_lon = lon;
|
||||
last_lat = lat;
|
||||
last_pos = p.osg();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rotation positon back to simple X-Z space.
|
||||
osg::Vec3 pos = last_pos;
|
||||
pos += u;
|
||||
|
||||
T.makeTranslate(pos);
|
||||
|
||||
osg::Matrix U = LAT*LON;
|
||||
osg::Vec3 x = osg::Vec3f(fieldSize, 0.0, 0.0)*U;
|
||||
osg::Vec3 y = osg::Vec3f(0.0, fieldSize, 0.0)*U;
|
||||
|
||||
// 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;
|
||||
osg::Matrix V;
|
||||
V.makeIdentity();
|
||||
V.invert(U*T);
|
||||
|
||||
osg::Vec3 q = pos*V;
|
||||
|
||||
// Shift the field if we've moved away from the centre box.
|
||||
if (q.x() > fieldSize) last_pos = last_pos + x;
|
||||
if (q.x() < -fieldSize) last_pos = last_pos - x;
|
||||
if (q.y() > fieldSize) last_pos = last_pos + y;
|
||||
if (q.y() < -fieldSize) last_pos = last_pos - y;
|
||||
|
||||
pos = last_pos;
|
||||
pos += u;
|
||||
|
||||
T.makeTranslate(pos);
|
||||
field_transform->setMatrix( LAT*LON*T );
|
||||
}
|
||||
|
||||
deltax += ax;
|
||||
deltay += ay;
|
||||
|
||||
last_lon = lon;
|
||||
last_lat = lat;
|
||||
}
|
||||
|
||||
|
||||
// correct the frustum with the right far plane
|
||||
ssgContext *context = ssgGetCurrentContext();
|
||||
frustum = *context->getFrustum();
|
||||
|
||||
float w, h;
|
||||
sgEnviro.getFOV( w, h );
|
||||
frustum.setFOV( w, h );
|
||||
frustum.setNearFar(1.0, CloudVis);
|
||||
timer_dt = dt;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
SGCloudField::SGCloudField() :
|
||||
field_root(new osg::Group),
|
||||
field_transform(new osg::MatrixTransform),
|
||||
field_group(new osg::Switch),
|
||||
deltax(0.0),
|
||||
deltay(0.0),
|
||||
last_lon(0.0),
|
||||
last_lat(0.0),
|
||||
last_course(0.0),
|
||||
last_density(0.0),
|
||||
draw_in_3d(true)
|
||||
defined3D(false)
|
||||
{
|
||||
#if 0
|
||||
sgSetVec3( relative_position, 0,0,0);
|
||||
theField.reserve(200);
|
||||
inViewClouds.reserve(200);
|
||||
sg_srandom_time_10();
|
||||
#else
|
||||
draw_in_3d = false;
|
||||
#endif
|
||||
field_root->addChild(field_transform.get());
|
||||
field_group->setName("3Dcloud");
|
||||
|
||||
// We duplicate the defined field group in a 3x3 array. This way,
|
||||
// we can simply shift entire groups around.
|
||||
for(int x = -1 ; x <= 1 ; x++) {
|
||||
for(int y = -1 ; y <= 1 ; y++ ) {
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> transform =
|
||||
new osg::PositionAttitudeTransform;
|
||||
transform->addChild(field_group.get());
|
||||
transform->setPosition(osg::Vec3(x*fieldSize, y * fieldSize, 0.0));
|
||||
|
||||
field_transform->addChild(transform.get());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SGCloudField::~SGCloudField() {
|
||||
#if 0
|
||||
list_of_Cloud::iterator iCloud;
|
||||
for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) {
|
||||
delete iCloud->aCloud;
|
||||
}
|
||||
theField.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SGCloudField::clear(void) {
|
||||
#if 0
|
||||
list_of_Cloud::iterator iCloud;
|
||||
for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) {
|
||||
delete iCloud->aCloud;
|
||||
}
|
||||
theField.clear();
|
||||
// force a recompute of density on first redraw
|
||||
last_density = 0.0;
|
||||
// true to come back in set density after layer is built
|
||||
draw_in_3d = true;
|
||||
#endif
|
||||
int num_children = field_group->getNumChildren();
|
||||
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
field_group->removeChild(i);
|
||||
}
|
||||
SGCloudField::defined3D = false;
|
||||
}
|
||||
|
||||
// use a table or else we see poping when moving the slider...
|
||||
@@ -285,248 +190,34 @@ static int densTable[][10] = {
|
||||
{1,1,1,1,1,1,1,1,1,1}
|
||||
};
|
||||
|
||||
// set the visible flag depending on density
|
||||
void SGCloudField::applyDensity(void) {
|
||||
#if 0
|
||||
int row = (int) (density / 10.0);
|
||||
int col = 0;
|
||||
sgBox fieldBox;
|
||||
|
||||
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;
|
||||
fieldBox.extend( *iCloud->aCloud->getCenter() );
|
||||
} else
|
||||
iCloud->visible = false;
|
||||
}
|
||||
last_density = density;
|
||||
draw_in_3d = ( theField.size() != 0);
|
||||
sgVec3 center;
|
||||
sgSubVec3( center, fieldBox.getMax(), fieldBox.getMin() );
|
||||
sgScaleVec3( center, 0.5f );
|
||||
center[1] = 0.0f;
|
||||
field_sphere.setCenter( center );
|
||||
field_sphere.setRadius( fieldSize * 0.5f * 1.414f );
|
||||
#endif
|
||||
int row = (int) (density / 10.0);
|
||||
int col = 0;
|
||||
int num_children = field_group->getNumChildren();
|
||||
|
||||
if (density != last_density) {
|
||||
// Switch on/off the children depending on the required density.
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
if (++col > 9) col = 0;
|
||||
if ( densTable[row][col] ) {
|
||||
field_group->setValue(i, true);
|
||||
} else {
|
||||
field_group->setValue(i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_density = density;
|
||||
}
|
||||
|
||||
// add one cloud, data is not copied, ownership given
|
||||
void SGCloudField::addCloud( sgVec3 pos, SGNewCloud *cloud) {
|
||||
#if 0
|
||||
Cloud cl;
|
||||
cl.aCloud = cloud;
|
||||
cl.visible = true;
|
||||
cloud->SetPos( pos );
|
||||
sgCopyVec3( cl.pos, *cloud->getCenter() );
|
||||
theField.push_back( cl );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static float Rnd(float n) {
|
||||
return n * (-0.5f + sg_random());
|
||||
}
|
||||
|
||||
// for debug only
|
||||
// build a field of cloud of size 25x25 km, its a grid of 11x11 clouds
|
||||
void SGCloudField::buildTestLayer(void) {
|
||||
#if 0
|
||||
const float s = 2250.0f;
|
||||
|
||||
for( int z = -5 ; z <= 5 ; z++) {
|
||||
for( int x = -5 ; x <= 5 ; x++ ) {
|
||||
SGNewCloud *cloud = new SGNewCloud(SGNewCloud::CLFamilly_cu);
|
||||
cloud->new_cu();
|
||||
sgVec3 pos = {(x+Rnd(0.7)) * s, 750.0f, (z+Rnd(0.7)) * s};
|
||||
addCloud(pos, cloud);
|
||||
}
|
||||
}
|
||||
applyDensity();
|
||||
#endif
|
||||
}
|
||||
|
||||
// cull all clouds of a tiled field
|
||||
void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) {
|
||||
#if 0
|
||||
list_of_Cloud::iterator iCloud;
|
||||
|
||||
sgSphere tile_sphere;
|
||||
tile_sphere.setRadius( field_sphere.getRadius() );
|
||||
sgVec3 tile_center;
|
||||
sgSubVec3( tile_center, field_sphere.getCenter(), eyePos );
|
||||
tile_sphere.setCenter( tile_center );
|
||||
tile_sphere.orthoXform(mat);
|
||||
if( frustum.contains( & tile_sphere ) == SG_OUTSIDE )
|
||||
return;
|
||||
|
||||
for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) {
|
||||
sgVec3 dist;
|
||||
sgSphere sphere;
|
||||
if( ! iCloud->visible )
|
||||
continue;
|
||||
sgSubVec3( dist, iCloud->pos, eyePos );
|
||||
sphere.setCenter(dist[0], dist[2], dist[1] + eyePos[1]);
|
||||
float radius = iCloud->aCloud->getRadius();
|
||||
sphere.setRadius(radius);
|
||||
sphere.orthoXform(mat);
|
||||
if( frustum.contains( & sphere ) != SG_OUTSIDE ) {
|
||||
float squareDist = dist[0]*dist[0] + dist[1]*dist[1] + dist[2]*dist[2];
|
||||
culledCloud tmp;
|
||||
tmp.aCloud = iCloud->aCloud;
|
||||
sgCopyVec3( tmp.eyePos, eyePos );
|
||||
// save distance for later sort, opposite distance because we want back to front
|
||||
tmp.dist = - squareDist;
|
||||
tmp.heading = -SG_PI/2.0 - atan2( dist[0], dist[2] ); // + SG_PI;
|
||||
tmp.alt = iCloud->pos[1];
|
||||
inViewClouds.push_back(tmp);
|
||||
if( squareDist - radius*radius < 100*100 )
|
||||
sgEnviro.set_view_in_cloud(true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Render a cloud field
|
||||
// because no field can have an infinite size (and we don't want to reach his border)
|
||||
// we draw this field and adjacent fields.
|
||||
// adjacent fields are not real, its the same field displaced by some offset
|
||||
void SGCloudField::Render(float *sun_color) {
|
||||
// sun_color used to depend on an extern SGSky *thesky definition
|
||||
// above. However, this is bad form for a library and it's much
|
||||
// more clean to just pass in the needed value. For reference, here is
|
||||
// the old way that sun_color was fetched ...
|
||||
// float *sun_color = thesky->get_sun_color();
|
||||
|
||||
#if 0
|
||||
sgVec3 eyePos;
|
||||
double relx, rely;
|
||||
|
||||
if( ! enable3D )
|
||||
return;
|
||||
|
||||
if( last_density != density ) {
|
||||
last_density = density;
|
||||
applyDensity();
|
||||
}
|
||||
|
||||
if( ! draw_in_3d )
|
||||
return;
|
||||
|
||||
if( ! SGNewCloud::cldCache->isRttAvailable() )
|
||||
return;
|
||||
|
||||
inViewClouds.clear();
|
||||
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
sgMat4 modelview, tmp, invtrans;
|
||||
|
||||
// try to find the sun position
|
||||
sgTransposeNegateMat4( invtrans, transform );
|
||||
sgVec3 lightVec;
|
||||
ssgGetLight( 0 )->getPosition( lightVec );
|
||||
sgXformVec3( lightVec, invtrans );
|
||||
|
||||
sgSetVec3( SGNewCloud::modelSunDir, lightVec[0], lightVec[2], lightVec[1]);
|
||||
// try to find the lighting data (not accurate)
|
||||
sgVec4 diffuse, ambient;
|
||||
ssgGetLight( 0 )->getColour( GL_DIFFUSE, diffuse );
|
||||
ssgGetLight( 0 )->getColour( GL_AMBIENT, ambient );
|
||||
// sgScaleVec3 ( SGNewCloud::sunlight, diffuse , 1.0f);
|
||||
sgScaleVec3 ( SGNewCloud::ambLight, ambient , 1.1f);
|
||||
// trying something else : clouds are more yellow/red at dawn/dusk
|
||||
// and added a bit of blue ambient
|
||||
sgScaleVec3 ( SGNewCloud::sunlight, sun_color , 0.4f);
|
||||
SGNewCloud::ambLight[2] += 0.1f;
|
||||
|
||||
sgVec3 delta_light;
|
||||
sgSubVec3(delta_light, last_sunlight, SGNewCloud::sunlight);
|
||||
if( (fabs(delta_light[0]) + fabs(delta_light[1]) + fabs(delta_light[2])) > 0.05f ) {
|
||||
sgCopyVec3( last_sunlight, SGNewCloud::sunlight );
|
||||
// force the redraw of all the impostors
|
||||
SGNewCloud::cldCache->invalidateCache();
|
||||
}
|
||||
|
||||
// voodoo things on the matrix stack
|
||||
ssgGetModelviewMatrix( modelview );
|
||||
sgCopyMat4( tmp, transform );
|
||||
sgPostMultMat4( tmp, modelview );
|
||||
|
||||
// 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 );
|
||||
|
||||
relx = fmod( relx + fieldSize, fieldSize );
|
||||
rely = fmod( rely + fieldSize, fieldSize );
|
||||
sgSetVec3( eyePos, relx, alt, rely);
|
||||
|
||||
sgSetVec3( view_X, tmp[0][0], tmp[1][0], tmp[2][0] );
|
||||
sgSetVec3( view_Y, tmp[0][1], tmp[1][1], tmp[2][1] );
|
||||
sgSetVec3( view_vec, tmp[0][2], tmp[1][2], tmp[2][2] );
|
||||
|
||||
ssgLoadModelviewMatrix( tmp );
|
||||
|
||||
/* flat earth
|
||||
|
||||
^
|
||||
|
|
||||
| FFF
|
||||
| FoF
|
||||
| FFF
|
||||
|
|
||||
O----------->
|
||||
o = we are here
|
||||
F = adjacent fields
|
||||
*/
|
||||
|
||||
for(int x = -1 ; x <= 1 ; x++)
|
||||
for(int y = -1 ; y <= 1 ; y++ ) {
|
||||
sgVec3 fieldPos;
|
||||
// pretend we are not where we are
|
||||
sgSetVec3(fieldPos, eyePos[0] + x*fieldSize, eyePos[1], eyePos[2] + y*fieldSize);
|
||||
cullClouds(fieldPos, tmp);
|
||||
}
|
||||
// sort all visible clouds back to front (because of transparency)
|
||||
std::sort( inViewClouds.begin(), inViewClouds.end() );
|
||||
|
||||
// TODO:push states
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER, 0.0f);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable(GL_SMOOTH);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glDisable( GL_FOG );
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// test data: field = 11x11 cloud, 9 fields
|
||||
// depending on position and view direction, perhaps 40 to 60 clouds not culled
|
||||
list_of_culledCloud::iterator iCloud;
|
||||
for( iCloud = inViewClouds.begin() ; iCloud != inViewClouds.end() ; iCloud++ ) {
|
||||
// iCloud->aCloud->drawContainers();
|
||||
iCloud->aCloud->Render(iCloud->eyePos);
|
||||
sgEnviro.callback_cloud(iCloud->heading, iCloud->alt,
|
||||
iCloud->aCloud->getRadius(), iCloud->aCloud->getFamilly(), - iCloud->dist, iCloud->aCloud->getId());
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
|
||||
glEnable( GL_FOG );
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
ssgLoadModelviewMatrix( modelview );
|
||||
|
||||
glPopMatrix();
|
||||
#endif
|
||||
void SGCloudField::addCloud( SGVec3f& pos, SGNewCloud *cloud) {
|
||||
defined3D = true;
|
||||
osg::ref_ptr<osg::LOD> lod = cloud->genCloud();
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> transform = new osg::PositionAttitudeTransform;
|
||||
|
||||
transform->setPosition(pos.osg());
|
||||
transform->addChild(lod.get());
|
||||
|
||||
field_group->addChild(transform.get());
|
||||
}
|
||||
|
||||
@@ -26,25 +26,22 @@
|
||||
#include <plib/sg.h>
|
||||
#include <simgear/compiler.h>
|
||||
#include <vector>
|
||||
#include <osgSim/Impostor>
|
||||
#include <osgDB/ReaderWriter>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Array>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/Switch>
|
||||
#include <osg/Billboard>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
using std::vector;
|
||||
|
||||
class SGNewCloud;
|
||||
|
||||
class culledCloud {
|
||||
public:
|
||||
SGNewCloud *aCloud;
|
||||
sgVec3 eyePos;
|
||||
float dist;
|
||||
float heading;
|
||||
float alt;
|
||||
bool operator<(const culledCloud &b) const {
|
||||
return (this->dist < b.dist);
|
||||
}
|
||||
};
|
||||
typedef vector<culledCloud> list_of_culledCloud;
|
||||
|
||||
/**
|
||||
* A layer of 3D clouds.
|
||||
*/
|
||||
@@ -58,27 +55,21 @@ private:
|
||||
bool visible;
|
||||
};
|
||||
|
||||
float Rnd(float);
|
||||
|
||||
typedef vector<Cloud> list_of_Cloud;
|
||||
|
||||
// cull all clouds of a tiled field
|
||||
void cullClouds(sgVec3 eyePos, sgMat4 mat);
|
||||
|
||||
void applyDensity(void);
|
||||
|
||||
list_of_Cloud theField;
|
||||
// this is a relative position only, with that we can move all clouds at once
|
||||
sgVec3 relative_position;
|
||||
// double lon, lat;
|
||||
// double lon, lat;
|
||||
|
||||
sgFrustum frustum;
|
||||
osg::ref_ptr<osg::Group> field_root;
|
||||
osg::ref_ptr<osg::MatrixTransform> field_transform;
|
||||
osg::ref_ptr<osg::Switch> field_group;
|
||||
|
||||
sgMat4 transform;
|
||||
double deltax, deltay, alt;
|
||||
double last_lon, last_lat, last_course;
|
||||
sgSphere field_sphere;
|
||||
double last_lon, last_lat, last_course;
|
||||
sgSphere field_sphere;
|
||||
float last_density;
|
||||
bool draw_in_3d;
|
||||
osg::Vec3 last_pos;
|
||||
|
||||
public:
|
||||
|
||||
@@ -88,18 +79,23 @@ public:
|
||||
void clear(void);
|
||||
|
||||
// add one cloud, data is not copied, ownership given
|
||||
void addCloud( sgVec3 pos, SGNewCloud *cloud);
|
||||
void addCloud( SGVec3f& pos, SGNewCloud *cloud);
|
||||
|
||||
// for debug only
|
||||
void buildTestLayer(void);
|
||||
/**
|
||||
* reposition the cloud layer at the specified origin and
|
||||
* orientation.
|
||||
* @param p position vector
|
||||
* @param up the local up vector
|
||||
* @param lon specifies a rotation about the Z axis
|
||||
* @param lat specifies a rotation about the new Y axis
|
||||
* @param spin specifies a rotation about the new Z axis
|
||||
* (and orients the sunrise/set effects)
|
||||
* @param dt the time elapsed since the last call
|
||||
*/
|
||||
bool reposition( const SGVec3f& p, const SGVec3f& up,
|
||||
double lon, double lat, double dt = 0.0 );
|
||||
|
||||
// Render a cloud field
|
||||
void Render( float *sun_color );
|
||||
|
||||
// reposition the cloud layer at the specified origin and orientation
|
||||
void reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double dt, float direction, float speed);
|
||||
|
||||
bool is3D(void) { return draw_in_3d; }
|
||||
osg::Group* getNode() { return field_root.get(); }
|
||||
|
||||
// visibility distance for clouds in meters
|
||||
static float CloudVis;
|
||||
@@ -109,20 +105,14 @@ public:
|
||||
static float density;
|
||||
static double timer_dt;
|
||||
static double fieldSize;
|
||||
static bool enable3D;
|
||||
|
||||
bool defined3D;
|
||||
|
||||
// return the size of the memory pool used by texture impostors
|
||||
static int get_CacheSize(void);
|
||||
static int get_CacheResolution(void);
|
||||
static float get_CloudVis(void) { return CloudVis; }
|
||||
static float get_density(void) { return density; }
|
||||
static bool get_enable3dClouds(void) { return enable3D; }
|
||||
|
||||
static void set_CacheSize(int sizeKb);
|
||||
static void set_CacheResolution(int resolutionPixels);
|
||||
static void set_CloudVis(float distance);
|
||||
static void set_density(float density);
|
||||
static void set_enable3dClouds(bool enable);
|
||||
|
||||
void applyDensity(void);
|
||||
};
|
||||
|
||||
#endif // _CLOUDFIELD_HXX
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@
|
||||
#include <simgear/compiler.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <osg/Fog>
|
||||
|
||||
#include "bbcache.hxx"
|
||||
|
||||
@@ -39,137 +40,47 @@ using std::vector;
|
||||
class SGNewCloud {
|
||||
|
||||
public:
|
||||
enum CLFamilly_type {
|
||||
CLFamilly_cu = 0,
|
||||
CLFamilly_cb,
|
||||
CLFamilly_st,
|
||||
CLFamilly_ns,
|
||||
CLFamilly_sc,
|
||||
CLFamilly_as,
|
||||
CLFamilly_ac,
|
||||
CLFamilly_ci,
|
||||
CLFamilly_cc,
|
||||
CLFamilly_cs,
|
||||
CLFamilly_nn
|
||||
};
|
||||
SGNewCloud(CLFamilly_type classification=CLFamilly_nn);
|
||||
SGNewCloud(string classification);
|
||||
SGNewCloud(const SGPath &tex_path,
|
||||
string tex,
|
||||
double min_w,
|
||||
double max_w,
|
||||
double min_h,
|
||||
double max_h,
|
||||
double min_sprite_w,
|
||||
double max_sprite_w,
|
||||
double min_sprite_h,
|
||||
double max_sprite_h,
|
||||
double b,
|
||||
int n,
|
||||
int nt_x,
|
||||
int nt_y);
|
||||
|
||||
~SGNewCloud();
|
||||
|
||||
enum CLbox_type {
|
||||
CLbox_standard = 0,
|
||||
CLbox_sc = 1,
|
||||
CLbox_cumulus = 2,
|
||||
CLbox_stratus = 3
|
||||
};
|
||||
|
||||
enum CLTexture_type {
|
||||
CLTexture_cumulus = 1,
|
||||
CLTexture_stratus = 2,
|
||||
CLTexture_max
|
||||
};
|
||||
// Generate a Cloud
|
||||
osg::ref_ptr<osg::LOD> genCloud ();
|
||||
|
||||
private:
|
||||
|
||||
class spriteDef {
|
||||
public:
|
||||
sgVec3 pos;
|
||||
float r;
|
||||
CLbox_type sprite_type;
|
||||
sgVec4 l0, l1, l2, l3;
|
||||
sgVec3 normal, n0, n1, n2, n3;
|
||||
int rank;
|
||||
int box;
|
||||
float dist; // distance used during sort
|
||||
bool operator<(const spriteDef &b) const {
|
||||
return (this->dist < b.dist);
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
sgVec3 pos;
|
||||
float r;
|
||||
// the type defines how the sprites can be positioned inside the box, their size, etc
|
||||
CLbox_type cont_type;
|
||||
sgVec3 center;
|
||||
} spriteContainer;
|
||||
|
||||
typedef vector<spriteDef> list_of_spriteDef;
|
||||
typedef vector<spriteContainer> list_of_spriteContainer;
|
||||
|
||||
void init(void);
|
||||
|
||||
void computeSimpleLight(sgVec3 eyePos);
|
||||
void addSprite(float x, float y, float z, float r, CLbox_type type, int box);
|
||||
|
||||
// sort on distance to eye because of transparency
|
||||
void sortSprite( sgVec3 eyePos );
|
||||
|
||||
// render the cloud on screen or on the RTT texture to build the impostor
|
||||
void Render3Dcloud( bool drawBB, sgVec3 eyePos, sgVec3 deltaPos, float dist_center );
|
||||
|
||||
// compute rotations so that a quad is facing the camera
|
||||
void CalcAngles(sgVec3 refpos, sgVec3 eyePos, float *angleY, float *angleX);
|
||||
|
||||
// draw a cloud but this time we use the impostor texture
|
||||
void RenderBB(sgVec3 deltaPos, bool first_time, float dist_center);
|
||||
|
||||
// determine if it is a good idea to use an impostor to render the cloud
|
||||
bool isBillboardable(float dist);
|
||||
|
||||
int cloudId, bbId;
|
||||
sgVec3 rotX, rotY;
|
||||
|
||||
// int rank;
|
||||
sgVec3 cloudpos, center;
|
||||
float delta_base;
|
||||
list_of_spriteDef list_spriteDef;
|
||||
list_of_spriteContainer list_spriteContainer;
|
||||
float radius;
|
||||
CLFamilly_type familly;
|
||||
|
||||
// fading data
|
||||
bool direction, fadeActive;
|
||||
float duration, pauseLength, fadetimer;
|
||||
float last_step;
|
||||
double min_width;
|
||||
double max_width;
|
||||
double min_height;
|
||||
double max_height;
|
||||
double min_sprite_width;
|
||||
double max_sprite_width;
|
||||
double min_sprite_height;
|
||||
double max_sprite_height;
|
||||
double bottom_shade;
|
||||
int num_sprites;
|
||||
int num_textures_x;
|
||||
int num_textures_y;
|
||||
const string texture;
|
||||
|
||||
osg::ref_ptr<osg::StateSet> stateSet;
|
||||
|
||||
public:
|
||||
// add a new box to the cloud
|
||||
void addContainer(float x, float y, float z, float r, CLbox_type type);
|
||||
|
||||
// generate all sprite with defined boxes
|
||||
void genSprites(void);
|
||||
|
||||
// debug only, define a cumulus
|
||||
void new_cu(void);
|
||||
|
||||
// debug only
|
||||
void drawContainers(void);
|
||||
|
||||
// define the new position of the cloud (inside the cloud field, not on sphere)
|
||||
void SetPos(sgVec3 newPos);
|
||||
|
||||
// render the cloud, fakepos is a relative position inside the cloud field
|
||||
void Render(sgVec3 fakepos);
|
||||
|
||||
//
|
||||
void startFade(bool direction, float duration, float pauseLength);
|
||||
void setFade(float howMuch);
|
||||
|
||||
inline float getRadius() { return radius; }
|
||||
inline sgVec3 *getCenter() { return ¢er; }
|
||||
inline int getId() { return cloudId; }
|
||||
|
||||
inline CLFamilly_type getFamilly(void) { return familly; }
|
||||
|
||||
// load all textures used to draw cloud sprites
|
||||
static void loadTextures( const string &tex_path );
|
||||
static sgVec3 modelSunDir;
|
||||
static sgVec3 sunlight, ambLight;
|
||||
static bool useAnisotropic;
|
||||
static float nearRadius;
|
||||
static bool lowQuality;
|
||||
static SGBbCache *cldCache;
|
||||
};
|
||||
|
||||
|
||||
#endif // _NEWCLOUD_HXX
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "sky.hxx"
|
||||
#include "cloudfield.hxx"
|
||||
#include "newcloud.hxx"
|
||||
|
||||
// Constructor
|
||||
SGSky::SGSky( void ) {
|
||||
@@ -43,6 +44,9 @@ SGSky::SGSky( void ) {
|
||||
ramp_down = 0.15;
|
||||
|
||||
in_cloud = -1;
|
||||
|
||||
clouds_3d_enabled = false;
|
||||
clouds_3d_density = 0.8;
|
||||
|
||||
pre_root = new osg::Group;
|
||||
pre_root->setNodeMask(simgear::BACKGROUND_BIT);
|
||||
@@ -85,7 +89,7 @@ void SGSky::build( double h_radius_m, double v_radius_m,
|
||||
|
||||
pre_selector->addChild( pre_transform.get() );
|
||||
|
||||
pre_root->addChild( pre_selector.get() );
|
||||
pre_root->addChild( pre_selector.get() );
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +165,8 @@ SGSky::add_cloud_layer( SGCloudLayer * layer )
|
||||
{
|
||||
cloud_layers.push_back(layer);
|
||||
cloud_root->addChild(layer->getNode());
|
||||
|
||||
layer->set_enable3dClouds(clouds_3d_enabled);
|
||||
}
|
||||
|
||||
const SGCloudLayer *
|
||||
@@ -181,6 +187,36 @@ SGSky::get_cloud_layer_count () const
|
||||
return cloud_layers.size();
|
||||
}
|
||||
|
||||
void SGSky::set_3dClouds(bool enable)
|
||||
{
|
||||
for ( unsigned i = 0; i < cloud_layers.size(); ++i ) {
|
||||
cloud_layers[i]->set_enable3dClouds(enable);
|
||||
}
|
||||
|
||||
clouds_3d_enabled = enable;
|
||||
}
|
||||
|
||||
bool SGSky::get_3dClouds() const {
|
||||
return clouds_3d_enabled;
|
||||
}
|
||||
|
||||
double SGSky::get_3dCloudDensity() const {
|
||||
return SGCloudField::get_density();
|
||||
}
|
||||
|
||||
void SGSky::set_3dCloudDensity(double density)
|
||||
{
|
||||
SGCloudField::set_density(density);
|
||||
|
||||
for ( unsigned i = 0; i < cloud_layers.size(); ++i ) {
|
||||
cloud_layers[i]->applyDensity();
|
||||
}
|
||||
}
|
||||
|
||||
void SGSky::texture_path( const string& path ) {
|
||||
tex_path = SGPath( path );
|
||||
}
|
||||
|
||||
// modify the current visibility based on cloud layers, thickness,
|
||||
// transition range, and simulated "puffs".
|
||||
void SGSky::modify_vis( float alt, float time_factor ) {
|
||||
@@ -214,7 +250,7 @@ void SGSky::modify_vis( float alt, float time_factor ) {
|
||||
}
|
||||
|
||||
if ( cloud_layers[i]->getCoverage() == SGCloudLayer::SG_CLOUD_CLEAR ||
|
||||
cloud_layers[i]->get_layer3D()->is3D() && SGCloudField::enable3D) {
|
||||
get_3dClouds()) {
|
||||
// do nothing, clear layers aren't drawn, don't affect
|
||||
// visibility andn dont' need to be faded in or out.
|
||||
} else if ( (cloud_layers[i]->getCoverage() ==
|
||||
@@ -311,3 +347,5 @@ void SGSky::modify_vis( float alt, float time_factor ) {
|
||||
|
||||
effective_visibility = effvis;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -237,6 +237,12 @@ private:
|
||||
double ramp_up; // in seconds
|
||||
double ramp_down; // in seconds
|
||||
|
||||
// 3D clouds enabled
|
||||
bool clouds_3d_enabled;
|
||||
|
||||
// 3D cloud density
|
||||
double clouds_3d_density;
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
@@ -338,9 +344,8 @@ public:
|
||||
* Specify the texture path (optional, defaults to current directory)
|
||||
* @param path base path to texture locations
|
||||
*/
|
||||
inline void texture_path( const string& path ) {
|
||||
tex_path = SGPath( path );
|
||||
}
|
||||
void texture_path( const string& path );
|
||||
|
||||
/** Enable drawing of the sky. */
|
||||
inline void enable() {
|
||||
pre_selector->setValue(0, 1);
|
||||
@@ -408,6 +413,23 @@ public:
|
||||
inline void set_visibility( float v ) {
|
||||
effective_visibility = visibility = (v <= 25.0) ? 25.0 : v;
|
||||
}
|
||||
|
||||
/** Get whether 3D clouds are enabled */
|
||||
virtual bool get_3dClouds() const;
|
||||
|
||||
/** Set whether 3D clouds are enabled
|
||||
* @param enable Whether to enable 3D clouds
|
||||
*/
|
||||
virtual void set_3dClouds(bool enable);
|
||||
|
||||
/** Get 3D cloud density */
|
||||
virtual double get_3dCloudDensity() const;
|
||||
|
||||
/** Set 3D cloud density
|
||||
* @param density 3D cloud density
|
||||
*/
|
||||
virtual void set_3dCloudDensity(double density);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user