<commit_before>/* -*-c++-*-
 *
 * Copyright (C) 2008 <NAME>
 *
 * 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 <algorithm>
#include <vector>
#include <string>
#include <map>

#include <boost/tuple/tuple_comparison.hpp>

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Math>
#include <osg/MatrixTransform>
#include <osg/Matrix>
#include <osg/NodeVisitor>

#include <osgDB/ReadFile>
#include <osgDB/FileUtils>

#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/scene/material/Effect.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/props/props.hxx>
#include <simgear/scene/util/QuadTreeBuilder.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/structure/OSGUtils.hxx>

#include "ShaderGeometry.hxx"
#include "TreeBin.hxx"

#define SG_TREE_QUAD_TREE_DEPTH 3
#define SG_TREE_FADE_OUT_LEVELS 10

using namespace osg;

namespace simgear
{

// Tree instance scheme:
// vertex - local position of quad vertex.
// normal - x y scaling, z number of varieties
// fog coord - rotation
// color - xyz of tree quad origin, replicated 4 times.
//
// The tree quad is rendered twice, with different rotations, to
// create the crossed tree geometry.

struct TreesBoundingBoxCallback : public Drawable::ComputeBoundingBoxCallback
{
    TreesBoundingBoxCallback() {}
    TreesBoundingBoxCallback(const TreesBoundingBoxCallback&, const CopyOp&) {}
    META_Object(simgear, TreesBoundingBoxCallback);
    virtual BoundingBox computeBound(const Drawable&) const;
};

BoundingBox
TreesBoundingBoxCallback::computeBound(const Drawable& drawable) const
{
    BoundingBox bb;
    const Geometry* geom = static_cast<const Geometry*>(&drawable);
    const Vec3Array* v = static_cast<const Vec3Array*>(geom->getVertexArray());
    const Vec3Array* pos = static_cast<const Vec3Array*>(geom->getColorArray());
    const Vec3Array* params
        = static_cast<const Vec3Array*>(geom->getNormalArray());
    const FloatArray* rot
        = static_cast<const FloatArray*>(geom->getFogCoordArray());
    float w = (*params)[0].x();
    float h = (*params)[0].y();
    Geometry::PrimitiveSetList primSets = geom->getPrimitiveSetList();
    FloatArray::const_iterator rotitr = rot->begin();
    for (Geometry::PrimitiveSetList::const_iterator psitr = primSets.begin(),
             psend = primSets.end();
         psitr != psend;
         ++psitr, ++rotitr) {
        Matrixd trnsfrm = (Matrixd::scale(w, w, h)
                           * Matrixd::rotate(*rotitr, Vec3(0.0f, 0.0f, 1.0f)));
        DrawArrays* da = static_cast<DrawArrays*>(psitr->get());
        GLint psFirst = da->getFirst();
        GLint psEndVert = psFirst + da->getCount();
        for (GLint i = psFirst;i < psEndVert; ++i) {
            Vec3 pt = (*v)[i];
            pt = pt * trnsfrm;
            pt += (*pos)[i];
            bb.expandBy(pt);
        }
    }
    return bb;
}

Geometry* makeSharedTreeGeometry(int numQuads)
{
    // generate a repeatable random seed
    mt seed;
    mt_init(&seed, unsigned(123));
    // set up the coords
    osg::Vec3Array* v = new osg::Vec3Array;
    osg::Vec2Array* t = new osg::Vec2Array;
    v->reserve(numQuads * 4);
    t->reserve(numQuads * 4);
    for (int i = 0; i < numQuads; ++i) {
        // Apply a random scaling factor and texture index.
        float h = (mt_rand(&seed) + mt_rand(&seed)) / 2.0f + 0.5f;
        float cw = h * .5;
        v->push_back(Vec3(0.0f, -cw, 0.0f));
        v->push_back(Vec3(0.0f, cw, 0.0f));
        v->push_back(Vec3(0.0f, cw, h));
        v->push_back(Vec3(0.0f,-cw, h));
        // The texture coordinate range is not the entire coordinate
        // space, as the texture has a number of different trees on
        // it. Here we assign random coordinates and let the shader
        // choose the variety.
        float variety = mt_rand(&seed);
        t->push_back(Vec2(variety, 0.0f));
        t->push_back(Vec2(variety + 1.0f, 0.0f));
        t->push_back(Vec2(variety + 1.0f, 1.0f));
        t->push_back(Vec2(variety, 1.0f));
    }
    Geometry* result = new Geometry;
    result->setVertexArray(v);
    result->setTexCoordArray(0, t);
    result->setComputeBoundingBoxCallback(new TreesBoundingBoxCallback);
    result->setUseDisplayList(false);
    return result;
}

ref_ptr<Geometry> sharedTreeGeometry;

Geometry* createTreeGeometry(float width, float height, int varieties)
{
    if (!sharedTreeGeometry)
        sharedTreeGeometry = makeSharedTreeGeometry(1600);
    Geometry* quadGeom = simgear::clone(sharedTreeGeometry.get(),<commit_msg>Use square textures for trees, with shrunk UV coordinates.<commit_after>/* -*-c++-*-
 *
 * Copyright (C) 2008 <NAME>
 *
 * 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 <algorithm>
#include <vector>
#include <string>
#include <map>

#include <boost/tuple/tuple_comparison.hpp>

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Math>
#include <osg/MatrixTransform>
#include <osg/Matrix>
#include <osg/NodeVisitor>

#include <osgDB/ReadFile>
#include <osgDB/FileUtils>

#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/scene/material/Effect.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/props/props.hxx>
#include <simgear/scene/util/QuadTreeBuilder.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/structure/OSGUtils.hxx>

#include "ShaderGeometry.hxx"
#include "TreeBin.hxx"

#define SG_TREE_QUAD_TREE_DEPTH 3
#define SG_TREE_FADE_OUT_LEVELS 10

using namespace osg;

namespace simgear
{

// Tree instance scheme:
// vertex - local position of quad vertex.
// normal - x y scaling, z number of varieties
// fog coord - rotation
// color - xyz of tree quad origin, replicated 4 times.
//
// The tree quad is rendered twice, with different rotations, to
// create the crossed tree geometry.

struct TreesBoundingBoxCallback : public Drawable::ComputeBoundingBoxCallback
{
    TreesBoundingBoxCallback() {}
    TreesBoundingBoxCallback(const TreesBoundingBoxCallback&, const CopyOp&) {}
    META_Object(simgear, TreesBoundingBoxCallback);
    virtual BoundingBox computeBound(const Drawable&) const;
};

BoundingBox
TreesBoundingBoxCallback::computeBound(const Drawable& drawable) const
{
    BoundingBox bb;
    const Geometry* geom = static_cast<const Geometry*>(&drawable);
    const Vec3Array* v = static_cast<const Vec3Array*>(geom->getVertexArray());
    const Vec3Array* pos = static_cast<const Vec3Array*>(geom->getColorArray());
    const Vec3Array* params
        = static_cast<const Vec3Array*>(geom->getNormalArray());
    const FloatArray* rot
        = static_cast<const FloatArray*>(geom->getFogCoordArray());
    float w = (*params)[0].x();
    float h = (*params)[0].y();
    Geometry::PrimitiveSetList primSets = geom->getPrimitiveSetList();
    FloatArray::const_iterator rotitr = rot->begin();
    for (Geometry::PrimitiveSetList::const_iterator psitr = primSets.begin(),
             psend = primSets.end();
         psitr != psend;
         ++psitr, ++rotitr) {
        Matrixd trnsfrm = (Matrixd::scale(w, w, h)
                           * Matrixd::rotate(*rotitr, Vec3(0.0f, 0.0f, 1.0f)));
        DrawArrays* da = static_cast<DrawArrays*>(psitr->get());
        GLint psFirst = da->getFirst();
        GLint psEndVert = psFirst + da->getCount();
        for (GLint i = psFirst;i < psEndVert; ++i) {
            Vec3 pt = (*v)[i];
            pt = pt * trnsfrm;
            pt += (*pos)[i];
            bb.expandBy(pt);
        }
    }
    return bb;
}

Geometry* makeSharedTreeGeometry(int numQuads)
{
    // generate a repeatable random seed
    mt seed;
    mt_init(&seed, unsigned(123));
    // set up the coords
    osg::Vec3Array* v = new osg::Vec3Array;
    osg::Vec2Array* t = new osg::Vec2Array;
    v->reserve(numQuads * 4);
    t->reserve(numQuads * 4);
    for (int i = 0; i < numQuads; ++i) {
        // Apply a random scaling factor and texture index.
        float h = (mt_rand(&seed) + mt_rand(&seed)) / 2.0f + 0.5f;
        float cw = h * .5;
        v->push_back(Vec3(0.0f, -cw, 0.0f));
        v->push_back(Vec3(0.0f, cw, 0.0f));
        v->push_back(Vec3(0.0f, cw, h));
        v->push_back(Vec3(0.0f,-cw, h));
        // The texture coordinate range is not the entire coordinate
        // space, as the texture has a number of different trees on
        // it. Here we assign random coordinates and let the shader
        // choose the variety.
        float variety = mt_rand(&seed);
        t->push_back(Vec2(variety, 0.0f));
        t->push_back(Vec2(variety + 1.0f, 0.0f));
        t->push_back(Vec2(variety + 1.0f, 0.234f));
        t->push_back(Vec2(variety, 0.234f));
    }
    Geometry* result = new Geometry;
    result->setVertexArray(v);
    result->setTexCoordArray(0, t);
    result->setComputeBoundingBoxCallback(new TreesBoundingBoxCallback);
    result->setUseDisplayList(false);
    return result;
}

ref_ptr<Geometry> sharedTreeGeometry;

Geometry* createTreeGeometry(float width, float height, int varieties)
{
    if (!sharedTreeGeometry)
        sharedTreeGeometry = makeSharedTreeGeometry(1600);
    Geometry* quadGeom = simgear::clone(sharedTreeGeometry.get(),
{'fraction_non_alphanumeric': 0.12485082162856881, 'fraction_numerical': 0.01652437345083999, 'mean_word_length': 3.5016528925619834, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 113, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '496358', 'n_tokens_mistral': 3638, 'n_tokens_neox': 3542, 'n_words': 953}