<commit_before>// a layer of 3d clouds
//
// Written by <NAME>, started April 2005.
//
// Copyright (C) 2005  <NAME> - <EMAIL>
//
// 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.
//
//

#ifdef HAVE_CONFIG_H
#  include <simgear_config.h>
#endif

#include <osg/Fog>
#include <osg/Texture2D>
#include <osg/PositionAttitudeTransform>
#include <osg/Vec4f>

#include <simgear/compiler.h>

#include <simgear/math/sg_random.h>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>

#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

using std::vector;

#include <simgear/environment/visual_enviro.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include <simgear/scene/util/SGUpdateVisitor.hxx>
#include "sky.hxx"
#include "newcloud.hxx"
#include "cloudfield.hxx"

#if defined(__MINGW32__)
#define isnan(x) _isnan(x)
#endif

#if defined (__FreeBSD__)
#  if __FreeBSD_version < 500000
     extern "C" {
       inline int isnan(double r) { return !(r <= 0 || r >= 0); }
     }
#  endif
#endif

using namespace simgear;

float SGCloudField::fieldSize = 50000.0f;
double SGCloudField::timer_dt = 0.0;
float SGCloudField::view_distance = 20000.0f;
bool SGCloudField::wrap = true;
float SGCloudField::RADIUS_LEVEL_1 = 20000.0f;
float SGCloudField::RADIUS_LEVEL_2 = 5000.0f;

SGVec3f SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;


// Reposition the cloud layer at the specified origin and orientation
bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
        		       double dt, int asl, float speed, float direction ) {
    // Determine any movement of the placed clouds
    if (placed_root->getNumChildren() == 0) return false;

    SGVec3<double> cart;
    SGGeodesy::SGGeodToCart(SGGeod::fromRadFt(lon, lat, 0.0f), cart);
    osg::Vec3f osg_pos = toOsg(cart);
    osg::Quat orient = toOsg(SGQuatd::fromLonLatRad(lon, lat) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
    
    // Always update the altitude transform, as this allows
    // the clouds to rise and fall smoothly depending on environment updates.
    osg::Vec3f alt = orient * osg::Vec3f(0.0f, 0.0f, (float) asl);
    altitude_transform->setPosition(alt);
    
    // Similarly, always determine the effects of the wind
    osg::Vec3f wind = osg::Vec3f(-cos((direction + 180)* SGD_DEGREES_TO_RADIANS) * speed * dt,
                                 sin((direction + 180)* SGD_DEGREES_TO_RADIANS) * speed * dt,
                                 0.0f);
    //cout << "Wind: " << direction << "@" << speed << "\n";
    
    osg::Vec3f windosg = field_transform->getAttitude() * wind;
    field_transform->setPosition(field_transform->getPosition() + windosg);
    
    if (!wrap) {
        // If we're not wrapping the cloudfield, then we make no effort to reposition
        return false;
        }
        
    if ((old_pos - osg_pos).length() > fieldSize*2) {
        // Big movement - reposition centered to current location.
        field_transform->setPosition(osg_pos);
        field_transform->setAttitude(orient);
        old_pos = osg_pos;
    } else {
        // delta is the vector from the old position to the new position in cloud-coords
        osg::Vec3f delta = field_transform->getAttitude().inverse() * (osg_pos - old_pos);
        //cout << "Delta: " << delta.length() << "\n";

        for (unsigned int i = 0; i < placed_root->getNumChildren(); i++) {
            osg::ref_ptr<osg::LOD> lodnode1 = (osg::LOD*) placed_root->getChild(i);
            osg::Vec3f v = delta - lodnode1->getCenter();

            if ((v.x() < -0.5*fieldSize) ||
                (v.x() >  0.5*fieldSize) ||
                (v.y() < -0.5*fieldSize) ||
                (v.y() >  0.5*fieldSize)   )  {
                //cout << "V: " << v.x() << ", " << v.y() << "\n";

                osg::Vec3f shift = osg::Vec3f(0.0f, 0.0f, 0.0f);
                if (v.x() > 0.5*fieldSize) { shift += osg::Vec3f(fieldSize, 0.0f, 0.0f); }
                if (v.x() < -0.5*fieldSize) { shift -= osg::Vec3f(fieldSize, 0.0f, 0.0f); }

                if (v.y() > 0.5*fieldSize) { shift += osg::Vec3f(0.0f, fieldSize, 0.0f); }
                if (v.y() < -0.5*fieldSize) { shift -= osg::Vec3f(0.0f, fieldSize, 0.0f); }

                //cout << "Shift: " << shift.x() << ", " << shift.y() << "\n\n";

                for (unsigned int j = 0; j < lodnode1->getNumChildren(); j++) {
                    osg::ref_ptr<osg::LOD> lodnode2 = (osg::LOD*) lodnode1->getChild(j);
                    for (unsigned int k = 0; k < lodnode2->getNumChildren(); k++) {
                        osg::ref_ptr<osg::PositionAttitudeTransform> pat =(osg::PositionAttitudeTransform*) lodnode2->getChild(k);
                        pat->setPosition(pat->getPosition() + shift);
                    }
        }
        }
        }
    }
    
    // Render the clouds in order from farthest away layer to nearest one.
    field_root->getStateSet()->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
    return true;
}

SGCloudField::SGCloudField() :
        field_root(new osg::Group),
        field_transform(new osg::PositionAttitudeTransform),
        altitude_transform(new osg::PositionAttitudeTransform)
{
    old_pos = osg::Vec3f(0.0f, 0.0f, 0.0f);
    field_root->addChild(field_transform.get());
    field_root->setName("3D Cloud field root");
    osg::StateSet *rootSet = field_root->getOrCreateStateSet();
    rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
    rootSet->setAttributeAndModes(getFog());
    
    field_transform->addChild(altitude_transform.get());
    placed_root = new osg::Group();
    altitude_transform->addChild(placed_root);
}
    
SGCloudField::~SGCloudField() {
        }
<commit_msg>Fix 3D cloud elevation<commit_after>// a layer of 3d clouds
//
// Written by <NAME>, started April 2005.
//
// Copyright (C) 2005  <NAME> - <EMAIL>
//
// 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.
//
//

#ifdef HAVE_CONFIG_H
#  include <simgear_config.h>
#endif

#include <osg/Fog>
#include <osg/Texture2D>
#include <osg/PositionAttitudeTransform>
#include <osg/Vec4f>

#include <simgear/compiler.h>

#include <simgear/math/sg_random.h>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>

#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

using std::vector;

#include <simgear/environment/visual_enviro.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include <simgear/scene/util/SGUpdateVisitor.hxx>
#include "sky.hxx"
#include "newcloud.hxx"
#include "cloudfield.hxx"

#if defined(__MINGW32__)
#define isnan(x) _isnan(x)
#endif

#if defined (__FreeBSD__)
#  if __FreeBSD_version < 500000
     extern "C" {
       inline int isnan(double r) { return !(r <= 0 || r >= 0); }
     }
#  endif
#endif

using namespace simgear;

float SGCloudField::fieldSize = 50000.0f;
double SGCloudField::timer_dt = 0.0;
float SGCloudField::view_distance = 20000.0f;
bool SGCloudField::wrap = true;
float SGCloudField::RADIUS_LEVEL_1 = 20000.0f;
float SGCloudField::RADIUS_LEVEL_2 = 5000.0f;

SGVec3f SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;


// Reposition the cloud layer at the specified origin and orientation
bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
        		       double dt, int asl, float speed, float direction ) {
    // Determine any movement of the placed clouds
    if (placed_root->getNumChildren() == 0) return false;

    SGVec3<double> cart;
    SGGeodesy::SGGeodToCart(SGGeod::fromRadFt(lon, lat, 0.0f), cart);
    osg::Vec3f osg_pos = toOsg(cart);
    osg::Quat orient = toOsg(SGQuatd::fromLonLatRad(lon, lat) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
    
    // Always update the altitude transform, as this allows
    // the clouds to rise and fall smoothly depending on environment updates.
    altitude_transform->setPosition(osg::Vec3f(0.0f, 0.0f, (float) asl));
    
    // Similarly, always determine the effects of the wind
    osg::Vec3f wind = osg::Vec3f(-cos((direction + 180)* SGD_DEGREES_TO_RADIANS) * speed * dt,
                                 sin((direction + 180)* SGD_DEGREES_TO_RADIANS) * speed * dt,
                                 0.0f);
    //cout << "Wind: " << direction << "@" << speed << "\n";
    
    osg::Vec3f windosg = field_transform->getAttitude() * wind;
    field_transform->setPosition(field_transform->getPosition() + windosg);
    
    if (!wrap) {
        // If we're not wrapping the cloudfield, then we make no effort to reposition
        return false;
    }
        
    if ((old_pos - osg_pos).length() > fieldSize*2) {
        // Big movement - reposition centered to current location.
        field_transform->setPosition(osg_pos);
        field_transform->setAttitude(orient);
        old_pos = osg_pos;
    } else {
        // delta is the vector from the old position to the new position in cloud-coords
        osg::Vec3f delta = field_transform->getAttitude().inverse() * (osg_pos - old_pos);
        //cout << "Delta: " << delta.length() << "\n";

        for (unsigned int i = 0; i < placed_root->getNumChildren(); i++) {
            osg::ref_ptr<osg::LOD> lodnode1 = (osg::LOD*) placed_root->getChild(i);
            osg::Vec3f v = delta - lodnode1->getCenter();

            if ((v.x() < -0.5*fieldSize) ||
                (v.x() >  0.5*fieldSize) ||
                (v.y() < -0.5*fieldSize) ||
                (v.y() >  0.5*fieldSize)   )  {
                //cout << "V: " << v.x() << ", " << v.y() << "\n";

                osg::Vec3f shift = osg::Vec3f(0.0f, 0.0f, 0.0f);
                if (v.x() > 0.5*fieldSize) { shift += osg::Vec3f(fieldSize, 0.0f, 0.0f); }
                if (v.x() < -0.5*fieldSize) { shift -= osg::Vec3f(fieldSize, 0.0f, 0.0f); }

                if (v.y() > 0.5*fieldSize) { shift += osg::Vec3f(0.0f, fieldSize, 0.0f); }
                if (v.y() < -0.5*fieldSize) { shift -= osg::Vec3f(0.0f, fieldSize, 0.0f); }

                //cout << "Shift: " << shift.x() << ", " << shift.y() << "\n\n";

                for (unsigned int j = 0; j < lodnode1->getNumChildren(); j++) {
                    osg::ref_ptr<osg::LOD> lodnode2 = (osg::LOD*) lodnode1->getChild(j);
                    for (unsigned int k = 0; k < lodnode2->getNumChildren(); k++) {
                        osg::ref_ptr<osg::PositionAttitudeTransform> pat =(osg::PositionAttitudeTransform*) lodnode2->getChild(k);
                        pat->setPosition(pat->getPosition() + shift);
                    }
                }
            }
        }
    }
    
    // Render the clouds in order from farthest away layer to nearest one.
    field_root->getStateSet()->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
    return true;
}

SGCloudField::SGCloudField() :
        field_root(new osg::Group),
        field_transform(new osg::PositionAttitudeTransform),
        altitude_transform(new osg::PositionAttitudeTransform)
{
    old_pos = osg::Vec3f(0.0f, 0.0f, 0.0f);
    field_root->addChild(field_transform.get());
    field_root->setName("3D Cloud field root");
    osg::StateSet *rootSet = field_root->getOrCreateStateSet();
    rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
    rootSet->setAttributeAndModes(getFog());
    
    field_transform->addChild(altitude_transform.get());
    placed_root = new osg::Group();
    altitude_transform->addChild(placed_root);
}
    
SGCloudField::~SGCloudField() {
        }

{'fraction_non_alphanumeric': 0.14133644133644133, 'fraction_numerical': 0.024087024087024088, 'mean_word_length': 2.8698135898977752, 'pattern_counts': {'":': 0, '<': 137, '<?xml version=': 0, '>': 111, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1861302', 'n_tokens_mistral': 4558, 'n_tokens_neox': 4302, 'n_words': 1071}