From 0dd50cf3d889ee1dd826f3fac70b8fb377dad0b2 Mon Sep 17 00:00:00 2001 From: ehofman Date: Thu, 7 Aug 2003 12:34:23 +0000 Subject: [PATCH] Add support for using textures as a basis for cloud fields. This is not yet completely finished. The orientation is not right. --- simgear/scene/sky/clouds3d/SkyArchive.cpp | 10 -- simgear/scene/sky/clouds3d/SkyCloud.cpp | 96 +++++++++++++++++++ simgear/scene/sky/clouds3d/SkyCloud.hpp | 1 + simgear/scene/sky/clouds3d/SkySceneLoader.cpp | 46 +++++++++ simgear/scene/sky/clouds3d/SkySceneLoader.hpp | 1 + .../scene/sky/clouds3d/SkySceneManager.cpp | 23 +++++ .../scene/sky/clouds3d/SkySceneManager.hpp | 1 + 7 files changed, 168 insertions(+), 10 deletions(-) diff --git a/simgear/scene/sky/clouds3d/SkyArchive.cpp b/simgear/scene/sky/clouds3d/SkyArchive.cpp index 256eb5ad..f5c8c648 100644 --- a/simgear/scene/sky/clouds3d/SkyArchive.cpp +++ b/simgear/scene/sky/clouds3d/SkyArchive.cpp @@ -26,16 +26,6 @@ #include -// FIXME: Remove this section whenever plib has it's own endian conversion -// funcrtions for 64-bit data types. -#ifndef ulEndianLittleDouble -// This hack doesn't actually do anything, but it's pressence -// marks the places that need endiannes attention. -inline double ulEndianLittleDouble(double x) { - return x; -} -#endif - struct SkyArchiveEntry { SkyArchiveEntry() : type(0), pData(NULL), iDataSize(0) {} diff --git a/simgear/scene/sky/clouds3d/SkyCloud.cpp b/simgear/scene/sky/clouds3d/SkyCloud.cpp index 843bc967..24078499 100644 --- a/simgear/scene/sky/clouds3d/SkyCloud.cpp +++ b/simgear/scene/sky/clouds3d/SkyCloud.cpp @@ -624,6 +624,102 @@ SkyMinMaxBox* SkyCloud::CopyBoundingVolume() const return pBox; } +SKYRESULT SkyCloud::Load(const unsigned char *data, unsigned int size, + float rScale, /* = 1.0f */ + double latitude, double longitude ) +{ + unsigned int iNumParticles; + Vec3f vecCenter = Vec3f::ZERO; + //Vec3f vecCenter; + //float rRadius; + + //_boundingBox.SetMin(vecCenter - Vec3f(rRadius, rRadius, rRadius)); + //_boundingBox.SetMax(vecCenter + Vec3f(rRadius, rRadius, rRadius)); + + for (unsigned int i = 0; i < size*size*4; i += 4) + { + Vec3f pos; + Vec4f color; + float radius; + + color.x = data[i]; // FIXME: Which unit? + color.y = data[i+1]; + color.z = data[i+2]; + color.w = data[i+3]; + + radius = (color.w/255) * rScale; + //radius = (color.x * color.y * color.z * color.w * rScale) / 4096; + + + pos.x = (i / (size*4)) * 10; // FIXME: Which unit? + pos.y = (i % (size*4)) * 10; + pos.z = radius / 2; + + if (radius > 0) + { + SkyCloudParticle *pParticle = new SkyCloudParticle((pos + vecCenter) * rScale, radius * rScale, color); + _boundingBox.AddPoint(pParticle->GetPosition()); + + _particles.push_back(pParticle); + } + } + + // this is just a bad hack to align cloud field from skyworks with local horizon at KSFO + // this "almost" works not quite the right solution okay to get some up and running + // we need to develop our own scheme for loading and positioning clouds + Mat33f R; + Vec3f moveit; + + R.Set( 0, 1, 0, + 1, 0, 0, + 0, 0, 1); + // clouds sit in the y-z plane and x-axis is the vertical cloud height + Rotate( R ); + +// rotate the cloud field about the fgfs z-axis based on initial longitude +float ex = 1.0; +float ey = 1.0; +float ez = 1.0; +float phi = longitude / 57.29578; +float one_min_cos = 1 - cos(phi); + +R.Set( +cos(phi) + one_min_cos*ex*ex, one_min_cos*ex*ey - ez*sin(phi), one_min_cos*ex*ez + ey*sin(phi), +one_min_cos*ex*ey + ez*sin(phi), cos(phi) + one_min_cos*ey*ey, one_min_cos*ey*ez - ex*sin(phi), +one_min_cos*ex*ez - ey*sin(phi), one_min_cos*ey*ez + ex*sin(phi), cos(phi) + one_min_cos*ez*ez ); + +Rotate( R ); + +// okay now that let's rotate about a vector for latitude where longitude forms the +// components of a unit vector in the x-y plane +ex = sin( longitude / 57.29578 ); +ey = -cos( longitude / 57.29578 ); +ez = 0.0; +phi = latitude / 57.29578; +one_min_cos = 1 - cos(phi); + +R.Set( +cos(phi) + one_min_cos*ex*ex, one_min_cos*ex*ey - ez*sin(phi), one_min_cos*ex*ez + ey*sin(phi), +one_min_cos*ex*ey + ez*sin(phi), cos(phi) + one_min_cos*ey*ey, one_min_cos*ey*ez - ex*sin(phi), +one_min_cos*ex*ez - ey*sin(phi), one_min_cos*ey*ez + ex*sin(phi), cos(phi) + one_min_cos*ez*ez ); + +Rotate( R ); +// need to calculate an offset to place the clouds at ~3000 feet MSL ATM this is an approximation +// to move the clouds to some altitude above sea level. At some locations this could be underground +// will need a better scheme to position clouds per user preferences +float cloud_level_msl = 3000.0f; + +float x_offset = ex * cloud_level_msl; +float y_offset = ey * cloud_level_msl; +float z_offset = cloud_level_msl * 0.5; +moveit.Set( x_offset, y_offset, z_offset ); + + Translate( moveit ); + + return SKYRESULT_OK; +} + + SKYRESULT SkyCloud::Load(const SkyArchive &archive, float rScale, /* = 1.0f */ double latitude, double longitude ) diff --git a/simgear/scene/sky/clouds3d/SkyCloud.hpp b/simgear/scene/sky/clouds3d/SkyCloud.hpp index d48bd5b4..9a608576 100644 --- a/simgear/scene/sky/clouds3d/SkyCloud.hpp +++ b/simgear/scene/sky/clouds3d/SkyCloud.hpp @@ -99,6 +99,7 @@ public: SKYRESULT Save(SkyArchive &archive) const; SKYRESULT Load(const SkyArchive &archive, float rScale = 1.0f,double latitude=0.0, double longitude=0.0); + SKYRESULT Load(const unsigned char *data, unsigned int size, float rScale = 1.0f,double latitude=0.0,double longitude=0.0); void Rotate(const Mat33f& rot); void Translate(const Vec3f& trans); diff --git a/simgear/scene/sky/clouds3d/SkySceneLoader.cpp b/simgear/scene/sky/clouds3d/SkySceneLoader.cpp index 1737622e..1f712ecb 100644 --- a/simgear/scene/sky/clouds3d/SkySceneLoader.cpp +++ b/simgear/scene/sky/clouds3d/SkySceneLoader.cpp @@ -89,6 +89,52 @@ SkySceneLoader::~SkySceneLoader() } + +//------------------------------------------------------------------------------ +// Function : SkySceneLoader::Load +// Description : +//------------------------------------------------------------------------------ +/** + * @fn SkySceneLoader::Load(std::string filename) + * @brief Loads a SkyWorks scene. + * + * This is a temporary fix, as it loads only limited scenes + * It can however, load any number of Cloud + + + */ +//bool SkySceneLoader::Load(std::string filepath) +bool SkySceneLoader::Load( unsigned char *data, unsigned int size, double latitude, double longitude ) +{ + // Need to create the managers + cout << "GraphicsContext::Instantiate();" << endl; + GraphicsContext::Instantiate(); + cout << " TextureManager::Instantiate();" << endl; + TextureManager::Instantiate(); + cout << " DynamicTextureManager::Instantiate();" << endl; + DynamicTextureManager::Instantiate(); + cout << " SceneManager::Instantiate();" << endl; + SceneManager::Instantiate(); + + float rScale = 40.0; + FAIL_RETURN(SceneManager::InstancePtr()->LoadClouds(data, size, rScale, latitude, longitude)); + + Vec3f dir(0, 0, 1); + pLight->SetPosition(Vec3f(0, 0, 17000)); + pLight->SetDirection(dir); + pLight->SetAmbient(Vec4f( 0.0f, 0.0f, 0.0f, 0.0f)); + pLight->SetDiffuse(Vec4f(1.0f, 1.0f, 1.0f, 0.0f)); + //pLight->SetDiffuse(Vec4f(0.0f, 0.0f, 0.0f, 0.0f)); + //pLight->SetSpecular(Vec4f(1.0f, 1.0f, 1.0f, 0.0f)); + + // No attenuation + pLight->SetAttenuation(1.0f, 0.0f, 0.0f); + SceneManager::InstancePtr()->AddLight(pLight); + + SceneManager::InstancePtr()->ShadeClouds(); + + return true; +} + //------------------------------------------------------------------------------ // Function : SkySceneLoader::Load // Description : diff --git a/simgear/scene/sky/clouds3d/SkySceneLoader.hpp b/simgear/scene/sky/clouds3d/SkySceneLoader.hpp index 7255ad3e..a78b9013 100644 --- a/simgear/scene/sky/clouds3d/SkySceneLoader.hpp +++ b/simgear/scene/sky/clouds3d/SkySceneLoader.hpp @@ -48,6 +48,7 @@ public: SkySceneLoader(); ~SkySceneLoader(); + bool Load( unsigned char *data, unsigned int size, double latitude, double longitude ); bool Load( SGPath fileroot, double latitude, double longitude ); void Set_Cloud_Orig( Point3D *posit ); diff --git a/simgear/scene/sky/clouds3d/SkySceneManager.cpp b/simgear/scene/sky/clouds3d/SkySceneManager.cpp index 07b36696..83d16002 100644 --- a/simgear/scene/sky/clouds3d/SkySceneManager.cpp +++ b/simgear/scene/sky/clouds3d/SkySceneManager.cpp @@ -499,6 +499,29 @@ SKYRESULT SkySceneManager::ShadeClouds() } +//------------------------------------------------------------------------------ +// Function : SkySceneManager::LoadClouds +// Description : +//------------------------------------------------------------------------------ +/** + * @fn SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale) + * @brief @todo + * + * @todo + */ +SKYRESULT SkySceneManager::LoadClouds(unsigned char *data, unsigned int size, float rScale, double latitude, double longitude) +{ + SkyCloud *pCloud = new SkyCloud(); + pCloud->Load(data, size, rScale, latitude, longitude); + SkyRenderableInstanceCloud *pInstance = new SkyRenderableInstanceCloud(pCloud, false); + AddCloud(pCloud); + AddCloudInstance(pInstance); + + RebuildCloudBVTree(); + return SKYRESULT_OK; +} + + //------------------------------------------------------------------------------ // Function : SkySceneManager::LoadClouds // Description : diff --git a/simgear/scene/sky/clouds3d/SkySceneManager.hpp b/simgear/scene/sky/clouds3d/SkySceneManager.hpp index 75b44286..783356fa 100644 --- a/simgear/scene/sky/clouds3d/SkySceneManager.hpp +++ b/simgear/scene/sky/clouds3d/SkySceneManager.hpp @@ -104,6 +104,7 @@ public: static void SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint); // load a set of clouds from an archive file. + SKYRESULT LoadClouds(unsigned char *data, unsigned int size, float rScale = 1.0f, double latitude=0.0, double longitude=0.0); SKYRESULT LoadClouds(SkyArchive& cloudArchive, float rScale = 1.0f, double latitude=0.0, double longitude=0.0); protected: // datatypes -- 2.39.5