Second trees patch from Stuart Buchanan
Adds random variation of tree texture maps
This commit is contained in:
parent
be61689458
commit
8cbe9f1bd0
@ -145,6 +145,11 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props
|
||||
tree_height = props->getDoubleValue("tree-height-m", 0.0);
|
||||
tree_width = props->getDoubleValue("tree-width-m", 0.0);
|
||||
tree_range = props->getDoubleValue("tree-range-m", 0.0);
|
||||
tree_varieties = props->getIntValue("tree-varieties", 1);
|
||||
|
||||
SGPath tpath( fg_root );
|
||||
tpath.append(props->getStringValue("tree-texture"));
|
||||
tree_texture = tpath.str();
|
||||
|
||||
// surface values for use with ground reactions
|
||||
solid = props->getBoolValue("solid", true);
|
||||
@ -181,14 +186,6 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props
|
||||
for (unsigned int i = 0; i < object_group_nodes.size(); i++)
|
||||
object_groups.push_back(new SGMatModelGroup(object_group_nodes[i]));
|
||||
|
||||
vector<SGPropertyNode_ptr> tree_texture_nodes =
|
||||
((SGPropertyNode *)props)->getChildren("tree-texture");
|
||||
for (unsigned int i = 0; i < tree_texture_nodes.size(); i++) {
|
||||
SGPath tpath( fg_root );
|
||||
tpath.append(tree_texture_nodes[i]->getStringValue());
|
||||
tree_textures.push_back(tpath.str());
|
||||
}
|
||||
|
||||
// read glyph table for taxi-/runway-signs
|
||||
vector<SGPropertyNode_ptr> glyph_nodes = props->getChildren("glyph");
|
||||
for (unsigned int i = 0; i < glyph_nodes.size(); i++) {
|
||||
|
@ -177,11 +177,18 @@ public:
|
||||
inline double get_tree_range () const { return tree_range; }
|
||||
|
||||
/**
|
||||
* Get the list of textures to use for trees in the forest
|
||||
* Get the number of tree varieties available
|
||||
*
|
||||
* @return the vector of forest textures to use.
|
||||
* @return the number of different trees defined in the texture strip
|
||||
*/
|
||||
inline vector<string> get_tree_textures () const { return tree_textures; }
|
||||
inline int get_tree_varieties () const { return tree_varieties; }
|
||||
|
||||
/**
|
||||
* Get the texture strip to use for trees
|
||||
*
|
||||
* @return the texture to use for trees.
|
||||
*/
|
||||
inline string get_tree_texture () const { return tree_texture; }
|
||||
|
||||
/**
|
||||
* Return if the surface material is solid, if it is not solid, a fluid
|
||||
@ -309,6 +316,9 @@ private:
|
||||
// Width of the tree
|
||||
double tree_width;
|
||||
|
||||
// Number of varieties of tree texture
|
||||
int tree_varieties;
|
||||
|
||||
// True if the material is solid, false if it is a fluid
|
||||
bool solid;
|
||||
|
||||
@ -336,8 +346,8 @@ private:
|
||||
// taxiway-/runway-sign texture elements
|
||||
map<string, SGSharedPtr<SGMaterialGlyph> > glyphs;
|
||||
|
||||
// The list of forest textures, used when creating trees
|
||||
vector<string> tree_textures;
|
||||
// Tree texture, typically a strip of applicable tree textures
|
||||
string tree_texture;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Internal constructors and methods.
|
||||
|
@ -263,7 +263,4 @@ SGMatModelGroup::get_object (int index) const
|
||||
return _objects[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// end of matmodel.cxx
|
||||
|
@ -54,15 +54,18 @@ SGReaderWriterBTG::readNode(const std::string& fileName,
|
||||
SGMaterialLib* matlib = 0;
|
||||
bool calcLights = false;
|
||||
bool useRandomObjects = false;
|
||||
bool useRandomVegetation = false;
|
||||
const SGReaderWriterBTGOptions* btgOptions
|
||||
= dynamic_cast<const SGReaderWriterBTGOptions*>(options);
|
||||
if (btgOptions) {
|
||||
matlib = btgOptions->getMatlib();
|
||||
calcLights = btgOptions->getCalcLights();
|
||||
useRandomObjects = btgOptions->getUseRandomObjects();
|
||||
useRandomVegetation = btgOptions->getUseRandomVegetation();
|
||||
}
|
||||
osg::Node* result = SGLoadBTG(fileName, matlib, calcLights,
|
||||
useRandomObjects);
|
||||
useRandomObjects,
|
||||
useRandomVegetation);
|
||||
if (result)
|
||||
return result;
|
||||
else
|
||||
|
@ -24,14 +24,17 @@ public:
|
||||
SGReaderWriterBTGOptions() {}
|
||||
SGReaderWriterBTGOptions(const std::string& str):
|
||||
osgDB::ReaderWriter::Options(str),
|
||||
_matlib(0), _calcLights(false), _useRandomObjects(false)
|
||||
_matlib(0), _calcLights(false),
|
||||
_useRandomObjects(false),
|
||||
_useRandomVegetation(false)
|
||||
{}
|
||||
|
||||
SGReaderWriterBTGOptions(const SGReaderWriterBTGOptions& options,
|
||||
const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
|
||||
osgDB::ReaderWriter::Options(options, copyop),
|
||||
_matlib(options._matlib), _calcLights(options._calcLights),
|
||||
_useRandomObjects(options._useRandomObjects)
|
||||
_useRandomObjects(options._useRandomObjects),
|
||||
_useRandomVegetation(options._useRandomVegetation)
|
||||
{
|
||||
}
|
||||
SGMaterialLib* getMatlib() const { return _matlib; }
|
||||
@ -39,15 +42,21 @@ public:
|
||||
bool getCalcLights() const { return _calcLights; }
|
||||
void setCalcLights(bool calcLights) { _calcLights = calcLights; }
|
||||
bool getUseRandomObjects() const { return _useRandomObjects; }
|
||||
bool getUseRandomVegetation() const { return _useRandomVegetation; }
|
||||
void setUseRandomObjects(bool useRandomObjects)
|
||||
{
|
||||
_useRandomObjects = useRandomObjects;
|
||||
}
|
||||
void setUseRandomVegetation(bool useRandomVegetation)
|
||||
{
|
||||
_useRandomVegetation = useRandomVegetation;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~SGReaderWriterBTGOptions() {}
|
||||
SGMaterialLib* _matlib;
|
||||
bool _calcLights;
|
||||
bool _useRandomObjects;
|
||||
|
||||
bool _useRandomVegetation;
|
||||
};
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/ParameterOutput>
|
||||
#include <simgear/screen/extensions.hxx>
|
||||
|
||||
#include "ShaderGeometry.hxx"
|
||||
|
||||
@ -32,10 +33,13 @@ namespace simgear
|
||||
{
|
||||
void ShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
|
||||
{
|
||||
for(PositionSizeList::const_iterator itr = _trees.begin();
|
||||
itr != _trees.end();
|
||||
++itr) {
|
||||
glColor4fv(itr->ptr());
|
||||
osg::State& state = *renderInfo.getState();
|
||||
const Extensions* extensions = getExtensions(state.getContextID(),true);
|
||||
|
||||
for(TreeBin::TreeList::const_iterator t = _trees.begin(); t != _trees.end(); ++t)
|
||||
{
|
||||
extensions->glVertexAttrib1f(1, (float) t->texture_index/varieties);
|
||||
glColor4f(t->position.x(), t->position.y(), t->position.z(), t->scale);
|
||||
_geometry->draw(renderInfo);
|
||||
}
|
||||
}
|
||||
@ -44,13 +48,13 @@ BoundingBox ShaderGeometry::computeBound() const
|
||||
{
|
||||
BoundingBox geom_box = _geometry->getBound();
|
||||
BoundingBox bb;
|
||||
for(PositionSizeList::const_iterator itr = _trees.begin();
|
||||
for(TreeBin::TreeList::const_iterator itr = _trees.begin();
|
||||
itr != _trees.end();
|
||||
++itr) {
|
||||
bb.expandBy(geom_box.corner(0)*(*itr)[3] +
|
||||
Vec3((*itr)[0], (*itr)[1], (*itr)[2]));
|
||||
bb.expandBy(geom_box.corner(7)*(*itr)[3] +
|
||||
Vec3((*itr)[0], (*itr)[1], (*itr)[2]));
|
||||
bb.expandBy(geom_box.corner(0)*itr->scale +
|
||||
osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() ));
|
||||
bb.expandBy(geom_box.corner(7)*itr->scale +
|
||||
osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() ));
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
@ -64,7 +68,7 @@ bool ShaderGeometry_readLocalData(Object& obj, Input& fr)
|
||||
if ((fr[0].matchWord("geometry"))) {
|
||||
++fr;
|
||||
iteratorAdvanced = true;
|
||||
Drawable* drawable = fr.readDrawable();
|
||||
osg::Drawable* drawable = fr.readDrawable();
|
||||
if (drawable) {
|
||||
geom._geometry = drawable;
|
||||
}
|
||||
@ -78,11 +82,15 @@ bool ShaderGeometry_readLocalData(Object& obj, Input& fr)
|
||||
iteratorAdvanced = true;
|
||||
// skip {
|
||||
while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
|
||||
Vec4 v;
|
||||
SGVec3f v;
|
||||
int t;
|
||||
float s;
|
||||
if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
|
||||
&& fr[2].getFloat(v.z()) && fr[3].getFloat(v.w())) {
|
||||
&& fr[2].getFloat(v.z()) && fr[3].getInt(t) && fr[4].getFloat(s)) {
|
||||
fr += 4;
|
||||
geom._trees.push_back(v);
|
||||
//SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
|
||||
//TreeBin::Tree tree = new TreeBin::Tree(v, t, s);
|
||||
geom._trees.push_back(TreeBin::Tree(v, t, s));
|
||||
} else {
|
||||
++fr;
|
||||
}
|
||||
@ -100,12 +108,12 @@ bool ShaderGeometry_writeLocalData(const Object& obj, Output& fw)
|
||||
fw.indent() << "instances " << geom._trees.size() << std::endl;
|
||||
fw.indent() << "{" << std::endl;
|
||||
fw.moveIn();
|
||||
for (ShaderGeometry::PositionSizeList::const_iterator iter
|
||||
for (TreeBin::TreeList::const_iterator iter
|
||||
= geom._trees.begin();
|
||||
iter != geom._trees.end();
|
||||
++iter) {
|
||||
fw.indent() << iter->x() << " " << iter->y() << " " << iter->z() << " "
|
||||
<< iter->w() << std::endl;
|
||||
fw.indent() << iter->position.x() << " " << iter->position.y() << " " << iter->position.z() << " "
|
||||
<< iter->texture_index << " " << iter->scale << std::endl;
|
||||
}
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
|
||||
#include "TreeBin.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
@ -43,6 +45,12 @@ class ShaderGeometry : public osg::Drawable
|
||||
setUseDisplayList(false);
|
||||
}
|
||||
|
||||
ShaderGeometry(int v) :
|
||||
varieties(v)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
}
|
||||
|
||||
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
||||
ShaderGeometry(const ShaderGeometry& ShaderGeometry,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
|
||||
osg::Drawable(ShaderGeometry,copyop) {}
|
||||
@ -60,14 +68,15 @@ class ShaderGeometry : public osg::Drawable
|
||||
_geometry = geometry;
|
||||
}
|
||||
|
||||
void addTree(const osg::Vec3& position, float scale)
|
||||
void addTree(TreeBin::Tree tree)
|
||||
{
|
||||
_trees.push_back(osg::Vec4(position, scale));
|
||||
_trees.push_back(tree);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Drawable> _geometry;
|
||||
|
||||
PositionSizeList _trees;
|
||||
TreeBin::TreeList _trees;
|
||||
int varieties;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -64,7 +64,7 @@ using namespace osg;
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
|
||||
osg::Geometry* createOrthQuads(float w, float h, int varieties, const osg::Matrix& rotate)
|
||||
{
|
||||
|
||||
//const osg::Vec3& pos = osg::Vec3(0.0f,0.0f,0.0f),
|
||||
@ -87,14 +87,19 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
|
||||
v[6].set( cw,0.0f,h);
|
||||
v[7].set(-cw,0.0f,h);
|
||||
|
||||
// The texture coordinate range is not the
|
||||
// entire coordinate space - as the texture
|
||||
// has a number of different trees on it.
|
||||
float tx = 1.0f/varieties;
|
||||
|
||||
t[0].set(0.0f,0.0f);
|
||||
t[1].set(1.0f,0.0f);
|
||||
t[2].set(1.0f,1.0f);
|
||||
t[1].set( tx,0.0f);
|
||||
t[2].set( tx,1.0f);
|
||||
t[3].set(0.0f,1.0f);
|
||||
|
||||
t[4].set(0.0f,0.0f);
|
||||
t[5].set(1.0f,0.0f);
|
||||
t[6].set(1.0f,1.0f);
|
||||
t[5].set( tx,0.0f);
|
||||
t[6].set( tx,1.0f);
|
||||
t[7].set(0.0f,1.0f);
|
||||
|
||||
// For now the normal is normal to the quad. If we want to get
|
||||
@ -122,10 +127,13 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
|
||||
}
|
||||
|
||||
static char vertexShaderSource[] =
|
||||
"varying vec2 texcoord;\n"
|
||||
"varying float fogFactor;\n"
|
||||
"attribute float textureIndex;\n"
|
||||
"\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" texcoord = gl_MultiTexCoord0.st + vec2(textureIndex, 0.0);\n"
|
||||
" vec3 position = gl_Vertex.xyz * gl_Color.w + gl_Color.xyz;\n"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);\n"
|
||||
" vec3 ecPosition = vec3(gl_ModelViewMatrix * vec4(position, 1.0));\n"
|
||||
@ -135,7 +143,7 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
|
||||
" vec4 ambientColor = gl_FrontLightModelProduct.sceneColor + gl_LightSource[0].ambient * gl_FrontMaterial.ambient;\n"
|
||||
" gl_FrontColor = ambientColor + gl_LightSource[0].diffuse * vec4(diffuse, 1.0);\n"
|
||||
" gl_BackColor = ambientColor + gl_LightSource[0].diffuse * vec4(backDiffuse, 1.0)\n;"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||
// " gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||
" float fogCoord = abs(ecPosition.z);\n"
|
||||
" fogFactor = exp( -gl_Fog.density * gl_Fog.density * fogCoord * fogCoord);\n"
|
||||
" fogFactor = clamp(fogFactor, 0.0, 1.0);\n"
|
||||
@ -143,13 +151,14 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
|
||||
|
||||
static char fragmentShaderSource[] =
|
||||
"uniform sampler2D baseTexture; \n"
|
||||
"varying vec2 texcoord;\n"
|
||||
// "varying vec3 N;\n"
|
||||
// "varying vec3 v;\n"
|
||||
"varying float fogFactor;\n"
|
||||
"\n"
|
||||
"void main(void) \n"
|
||||
"{ \n"
|
||||
" vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);\n"
|
||||
" vec4 base = texture2D( baseTexture, texcoord);\n"
|
||||
|
||||
" vec4 finalColor = base * gl_Color;\n"
|
||||
" gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor );\n"
|
||||
@ -164,22 +173,23 @@ namespace
|
||||
{
|
||||
struct MakeTreesLeaf
|
||||
{
|
||||
MakeTreesLeaf(float range, Geometry* geometry) :
|
||||
_range(range), _geometry(geometry)
|
||||
MakeTreesLeaf(float range, Geometry* geometry, int varieties) :
|
||||
_range(range), _geometry(geometry), _varieties(varieties)
|
||||
{}
|
||||
MakeTreesLeaf(const MakeTreesLeaf& rhs) :
|
||||
_range(rhs._range), _geometry(rhs._geometry) {}
|
||||
_range(rhs._range), _geometry(rhs._geometry), _varieties(rhs._varieties) {}
|
||||
LOD* operator() () const
|
||||
{
|
||||
LOD* result = new LOD;
|
||||
Geode* geode = new Geode;
|
||||
ShaderGeometry* sg = new ShaderGeometry;
|
||||
ShaderGeometry* sg = new ShaderGeometry(_varieties);
|
||||
sg->setGeometry(_geometry);
|
||||
geode->addDrawable(sg);
|
||||
result->addChild(geode, 0, _range);
|
||||
return result;
|
||||
}
|
||||
float _range;
|
||||
int _varieties;
|
||||
Geometry* _geometry;
|
||||
};
|
||||
|
||||
@ -190,7 +200,7 @@ struct AddTreesLeafObject
|
||||
Geode* geode = static_cast<Geode*>(lod->getChild(0));
|
||||
ShaderGeometry* sg
|
||||
= static_cast<ShaderGeometry*>(geode->getDrawable(0));
|
||||
sg->addTree(tree.position.osg(), tree.height);
|
||||
sg->addTree(tree);
|
||||
}
|
||||
};
|
||||
|
||||
@ -212,22 +222,20 @@ typedef QuadTreeBuilder<LOD*, TreeBin::Tree, MakeTreesLeaf, AddTreesLeafObject,
|
||||
osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
|
||||
{
|
||||
// Set up some shared structures.
|
||||
// FIXME: Currently we only take the texture, height and width of the first tree in the forest. In the future
|
||||
// we should be able to handle multiple textures etc.
|
||||
TreeBin::Tree firstTree = forest.getTree(0);
|
||||
|
||||
osg::Geometry* shared_geometry = createOrthQuads(firstTree.width,
|
||||
firstTree.height,
|
||||
osg::Geometry* shared_geometry = createOrthQuads(forest.width,
|
||||
forest.height,
|
||||
forest.texture_varieties,
|
||||
transform);
|
||||
|
||||
ref_ptr<Group> group;
|
||||
|
||||
osg::StateSet* stateset = 0;
|
||||
StateSetMap::iterator iter = treeTextureMap.find(firstTree.texture);
|
||||
StateSetMap::iterator iter = treeTextureMap.find(forest.texture);
|
||||
if (iter == treeTextureMap.end()) {
|
||||
osg::Texture2D *tex = new osg::Texture2D;
|
||||
tex->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP );
|
||||
tex->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP );
|
||||
tex->setImage(osgDB::readImageFile(firstTree.texture));
|
||||
tex->setImage(osgDB::readImageFile(forest.texture));
|
||||
|
||||
static ref_ptr<AlphaFunc> alphaFunc;
|
||||
static ref_ptr<Program> program;
|
||||
@ -244,6 +252,8 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
|
||||
baseTextureSampler = new osg::Uniform("baseTexture", 0);
|
||||
Shader* vertex_shader = new Shader(Shader::VERTEX, vertexShaderSource);
|
||||
program->addShader(vertex_shader);
|
||||
program->addBindAttribLocation("textureIndex", 1);
|
||||
|
||||
Shader* fragment_shader = new Shader(Shader::FRAGMENT,
|
||||
fragmentShaderSource);
|
||||
program->addShader(fragment_shader);
|
||||
@ -260,9 +270,8 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
|
||||
stateset->addUniform(baseTextureSampler.get());
|
||||
stateset->setMode(GL_VERTEX_PROGRAM_TWO_SIDE, StateAttribute::ON);
|
||||
stateset->setAttribute(material.get());
|
||||
// XXX This should really come from a material definition
|
||||
// instead of being hard-coded.
|
||||
treeTextureMap.insert(StateSetMap::value_type(firstTree.texture,
|
||||
|
||||
treeTextureMap.insert(StateSetMap::value_type(forest.texture,
|
||||
stateset));
|
||||
} else {
|
||||
stateset = iter->second.get();
|
||||
@ -272,8 +281,9 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
|
||||
ShaderGeometryQuadtree quadtree(GetTreeCoord(Matrix::inverse(transform)),
|
||||
AddTreesLeafObject(),
|
||||
SG_TREE_QUAD_TREE_DEPTH,
|
||||
MakeTreesLeaf(firstTree.range,
|
||||
shared_geometry));
|
||||
MakeTreesLeaf(forest.range,
|
||||
shared_geometry,
|
||||
forest.texture_varieties));
|
||||
quadtree.buildQuadTree(forest._trees.begin(), forest._trees.end());
|
||||
group = quadtree.getRoot();
|
||||
}
|
||||
|
@ -23,33 +23,39 @@
|
||||
#define TREE_BIN_HXX
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/Matrix>
|
||||
|
||||
#include <simgear/math/SGVec3.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
class TreeBin {
|
||||
public:
|
||||
struct Tree {
|
||||
Tree(const SGVec3f& p, string t, float h, float w, double r) :
|
||||
position(p), texture(t), height(h), width(w), range(r)
|
||||
Tree(const SGVec3f& p, int t, float s) :
|
||||
position(p), texture_index(t), scale(s)
|
||||
{ }
|
||||
SGVec3f position;
|
||||
string texture;
|
||||
int texture_index;
|
||||
float scale;
|
||||
};
|
||||
|
||||
typedef std::vector<Tree> TreeList;
|
||||
|
||||
int texture_varieties;
|
||||
double range;
|
||||
float height;
|
||||
float width;
|
||||
double range;
|
||||
};
|
||||
typedef std::vector<Tree> TreeList;
|
||||
std::string texture;
|
||||
|
||||
void insert(const Tree& t)
|
||||
{ _trees.push_back(t); }
|
||||
void insert(const SGVec3f& p, string t, float h, float w, double r)
|
||||
{ insert(Tree(p, t, h, w, r)); }
|
||||
void insert(const SGVec3f& p, int t, float s)
|
||||
{ insert(Tree(p, t, s)); }
|
||||
|
||||
unsigned getNumTrees() const
|
||||
{ return _trees.size(); }
|
||||
|
@ -468,15 +468,23 @@ struct SGTileGeometryBin {
|
||||
if (coverage <= 0)
|
||||
continue;
|
||||
|
||||
vector<string> textures = mat->get_tree_textures();
|
||||
// Attributes that don't vary by tree
|
||||
randomForest.texture = mat->get_tree_texture();
|
||||
randomForest.range = mat->get_tree_range();
|
||||
randomForest.width = mat->get_tree_width();
|
||||
randomForest.height = mat->get_tree_height();
|
||||
randomForest.texture_varieties = mat->get_tree_varieties();
|
||||
|
||||
std::vector<SGVec3f> randomPoints;
|
||||
i->second.addRandomSurfacePoints(coverage, 0, randomPoints);
|
||||
std::vector<SGVec3f>::iterator j;
|
||||
for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {
|
||||
int k = (int)(mt_rand(&seed) * textures.size());
|
||||
if (k == textures.size()) k--;
|
||||
randomForest.insert(*j, textures[k], mat->get_tree_height(), mat->get_tree_width(), mat->get_tree_range());
|
||||
|
||||
// Apply a random scaling factor and texture index.
|
||||
float scale = (mt_rand(&seed) + mt_rand(&seed)) / 2.0f + 0.5f;
|
||||
int v = (int) (mt_rand(&seed) * mat->get_tree_varieties());
|
||||
if (v == mat->get_tree_varieties()) v--;
|
||||
randomForest.insert(*j, v, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -559,7 +567,7 @@ typedef QuadTreeBuilder<osg::LOD*, ModelLOD, MakeQuadLeaf, AddModelLOD,
|
||||
GetModelLODCoord> RandomObjectsQuadtree;
|
||||
|
||||
osg::Node*
|
||||
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects)
|
||||
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation)
|
||||
{
|
||||
SGBinObject tile;
|
||||
if (!tile.read_bin(path))
|
||||
@ -641,6 +649,8 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
|
||||
randomObjects->setName("random objects");
|
||||
}
|
||||
|
||||
if (use_random_vegetation)
|
||||
{
|
||||
// Now add some random forest.
|
||||
tileGeometryBin.computeRandomForest(matlib);
|
||||
|
||||
@ -649,6 +659,7 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
|
||||
randomForest->setName("random trees");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (calc_lights) {
|
||||
// FIXME: ugly, has a side effect
|
||||
|
@ -56,6 +56,6 @@ inline bool SGGenTile( const std::string&, const SGBucket& b,
|
||||
}
|
||||
|
||||
osg::Node*
|
||||
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects);
|
||||
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation);
|
||||
|
||||
#endif // _SG_OBJ_HXX
|
||||
|
Loading…
Reference in New Issue
Block a user