From e5995208a9e8e5b152147e1ec22d5a5ea45fbfd0 Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Thu, 19 Feb 2015 21:14:07 +0000 Subject: [PATCH] Support for tree shadows from Thorsten RENK. --- simgear/scene/tgdb/SGNodeTriangles.hxx | 5 +- simgear/scene/tgdb/SGTexturedTriangleBin.hxx | 5 +- simgear/scene/tgdb/SGTileDetailsCallback.hxx | 11 ++-- simgear/scene/tgdb/TreeBin.cxx | 54 +++++++++++++++++--- simgear/scene/tgdb/TreeBin.hxx | 11 ++-- 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/simgear/scene/tgdb/SGNodeTriangles.hxx b/simgear/scene/tgdb/SGNodeTriangles.hxx index 9ec37658..1d3f72d2 100644 --- a/simgear/scene/tgdb/SGNodeTriangles.hxx +++ b/simgear/scene/tgdb/SGNodeTriangles.hxx @@ -291,7 +291,8 @@ public: float vegetation_density, float cos_max_density_angle, float cos_zero_density_angle, - std::vector& points) + std::vector& points, + std::vector& normals) { if ( !geometries.empty() ) { const osg::Vec3Array* vertices = dynamic_cast(geometries[0]->getVertexArray()); @@ -366,9 +367,11 @@ public: if (mt_rand(&seed) < img->getColor(x, y).g()) { // The red channel contains the rotation for this object points.push_back(randomPoint); + normals.push_back(normalize(normal)); } } else { points.push_back(randomPoint); + normals.push_back(normalize(normal)); } } } diff --git a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx index b2fb3cd5..47939a75 100644 --- a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx +++ b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx @@ -216,7 +216,8 @@ public: float vegetation_density, float cos_max_density_angle, float cos_zero_density_angle, - std::vector& points) + std::vector& points, + std::vector& normals) { unsigned num = getNumTriangles(); for (unsigned i = 0; i < num; ++i) { @@ -282,9 +283,11 @@ public: if (mt_rand(&seed) < img->getColor(x, y).g()) { // The red channel contains the rotation for this object points.push_back(randomPoint); + normals.push_back(normalize(normal)); } } else { points.push_back(randomPoint); + normals.push_back(normalize(normal)); } } } diff --git a/simgear/scene/tgdb/SGTileDetailsCallback.hxx b/simgear/scene/tgdb/SGTileDetailsCallback.hxx index ced1403c..fbee88f8 100644 --- a/simgear/scene/tgdb/SGTileDetailsCallback.hxx +++ b/simgear/scene/tgdb/SGTileDetailsCallback.hxx @@ -723,7 +723,7 @@ public: BOOST_FOREACH(bin, randomForest) { if ((bin->texture == mat->get_tree_texture() ) && - (bin->teffect == mat->get_tree_effect() ) && + (bin->teffect == mat->get_tree_effect() ) && (bin->texture_varieties == mat->get_tree_varieties()) && (bin->range == mat->get_tree_range() ) && (bin->width == mat->get_tree_width() ) && @@ -747,16 +747,19 @@ public: } std::vector randomPoints; + std::vector randomPointNormals; matTris[i].addRandomTreePoints(wood_coverage, mat->get_one_object_mask(matTris[i].getTextureIndex()), vegetation_density, mat->get_cos_tree_max_density_slope_angle(), mat->get_cos_tree_zero_density_slope_angle(), - randomPoints); + randomPoints, + randomPointNormals); std::vector::iterator k; - for (k = randomPoints.begin(); k != randomPoints.end(); ++k) { - bin->insert(*k); + std::vector::iterator j; + for (k = randomPoints.begin(), j = randomPointNormals.begin(); k != randomPoints.end(); ++k, ++j) { + bin->insert(*k, *j); } } } diff --git a/simgear/scene/tgdb/TreeBin.cxx b/simgear/scene/tgdb/TreeBin.cxx index 64928084..953b9360 100644 --- a/simgear/scene/tgdb/TreeBin.cxx +++ b/simgear/scene/tgdb/TreeBin.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include "ShaderGeometry.hxx" @@ -62,6 +63,9 @@ using namespace osg; namespace simgear { +bool use_tree_shadows; +bool use_tree_normals; + // Tree instance scheme: // vertex - local position of quad vertex. // normal - x y scaling, z number of varieties @@ -164,15 +168,24 @@ Geometry* createTreeGeometry(float width, float height, int varieties) // Positions quadGeom->setColorArray(new Vec3Array); quadGeom->setColorBinding(Geometry::BIND_PER_VERTEX); - FloatArray* rotation = new FloatArray(2); + // Normals + if (use_tree_shadows || use_tree_normals) + { + quadGeom->setSecondaryColorArray(new Vec3Array); + quadGeom->setSecondaryColorBinding(Geometry::BIND_PER_VERTEX); + } + FloatArray* rotation = new FloatArray(3); (*rotation)[0] = 0.0; (*rotation)[1] = PI_2; + if (use_tree_shadows) {(*rotation)[2] = -1.0;} quadGeom->setFogCoordArray(rotation); quadGeom->setFogCoordBinding(Geometry::BIND_PER_PRIMITIVE_SET); // The primitive sets render the same geometry, but the second // will rotated 90 degrees by the vertex shader, which uses the // fog coordinate as a rotation. - for (int i = 0; i < 2; ++i) + int imax = 2; + if (use_tree_shadows) {imax = 3;} + for (int i = 0; i < imax; ++i) quadGeom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS)); return quadGeom; } @@ -184,13 +197,17 @@ EffectGeode* createTreeGeode(float width, float height, int varieties) return result; } -void addTreeToLeafGeode(Geode* geode, const SGVec3f& p) +void addTreeToLeafGeode(Geode* geode, const SGVec3f& p, const SGVec3f& t) { Vec3 pos = toOsg(p); + Vec3 ter = toOsg(t); unsigned int numDrawables = geode->getNumDrawables(); Geometry* geom = static_cast(geode->getDrawable(numDrawables - 1)); Vec3Array* posArray = static_cast(geom->getColorArray()); + Vec3Array* tnormalArray; + if (use_tree_shadows || use_tree_normals) + {tnormalArray = static_cast(geom->getSecondaryColorArray());} if (posArray->size() >= static_cast(geom->getVertexArray())->size()) { Vec3Array* paramsArray @@ -198,11 +215,17 @@ void addTreeToLeafGeode(Geode* geode, const SGVec3f& p) Vec3 params = (*paramsArray)[0]; geom = createTreeGeometry(params.x(), params.y(), params.z()); posArray = static_cast(geom->getColorArray()); + if (use_tree_shadows || use_tree_normals) + {tnormalArray = static_cast(geom->getSecondaryColorArray());} geode->addDrawable(geom); } posArray->insert(posArray->end(), 4, pos); + if (use_tree_shadows || use_tree_normals) + {tnormalArray->insert(tnormalArray->end(),4,ter);} size_t numVerts = posArray->size(); - for (int i = 0; i < 2; ++i) { + int imax = 2; + if (use_tree_shadows) {imax = 3;} + for (int i = 0; i < imax; ++i) { DrawArrays* primSet = static_cast(geom->getPrimitiveSet(i)); primSet->setCount(numVerts); @@ -218,14 +241,14 @@ namespace { struct MakeTreesLeaf { - MakeTreesLeaf(float range, int varieties, float width, float height, + MakeTreesLeaf(float range, int varieties, float width, float height, Effect* effect) : _range(range), _varieties(varieties), _width(width), _height(height), _effect(effect) {} MakeTreesLeaf(const MakeTreesLeaf& rhs) : _range(rhs._range), - _varieties(rhs._varieties), _width(rhs._width), _height(rhs._height), + _varieties(rhs._varieties), _width(rhs._width), _height(rhs._height), _effect(rhs._effect) {} @@ -255,7 +278,7 @@ struct AddTreesLeafObject void operator() (LOD* lod, const TreeBin::Tree& tree) const { Geode* geode = static_cast(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren())); - addTreeToLeafGeode(geode, tree.position); + addTreeToLeafGeode(geode, tree.position, tree.tnormal); } }; @@ -277,7 +300,8 @@ struct TreeTransformer TreeBin::Tree operator()(const TreeBin::Tree& tree) const { Vec3 pos = toOsg(tree.position); - return TreeBin::Tree(toSG(pos * mat)); + Vec3 norm = toOsg(tree.tnormal); + return TreeBin::Tree(toSG(pos * mat),toSG(norm * mat)); } Matrix mat; }; @@ -332,6 +356,20 @@ osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform MatrixTransform* mt = new MatrixTransform(transform); SGTreeBinList::iterator i; + + use_tree_shadows = false; + use_tree_normals = false; + if (options) { + SGPropertyNode* propertyNode = options->getPropertyNode().get(); + if (propertyNode) { + use_tree_shadows + = propertyNode->getBoolValue("/sim/rendering/random-vegetation-shadows", + use_tree_shadows); + use_tree_normals + = propertyNode->getBoolValue("/sim/rendering/random-vegetation-normals", + use_tree_normals); + } + } for (i = forestList.begin(); i != forestList.end(); ++i) { TreeBin* forest = *i; diff --git a/simgear/scene/tgdb/TreeBin.hxx b/simgear/scene/tgdb/TreeBin.hxx index 80441ec4..5f97d4f5 100644 --- a/simgear/scene/tgdb/TreeBin.hxx +++ b/simgear/scene/tgdb/TreeBin.hxx @@ -36,10 +36,10 @@ namespace simgear class TreeBin { public: struct Tree { - Tree(const SGVec3f& p) : - position(p) - { } SGVec3f position; + SGVec3f tnormal; + Tree(const SGVec3f& p, const SGVec3f& t) : position(p),tnormal(t) + { } }; typedef std::vector TreeList; @@ -53,8 +53,9 @@ public: void insert(const Tree& t) { _trees.push_back(t); } - void insert(const SGVec3f& p, int t, float s) - { insert(Tree(p)); } + + void insert(const SGVec3f& p, const SGVec3f& tnorm) + {insert(Tree(p,tnorm));} unsigned getNumTrees() const { return _trees.size(); } -- 2.39.5