From 3c74fea08760810234c7175cdcabe3eaf334d80a Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 21 Jan 2009 22:20:03 +0100 Subject: [PATCH 1/2] Rewrite ShaderGeometry to use display lists and OSG primitives. Based on a patch from Yon Uriarte. Eliminate _trees list from ShaderGeometry Use the position and scale values that are already available. --- simgear/scene/tgdb/ShaderGeometry.cxx | 89 +++++++++++---------------- simgear/scene/tgdb/ShaderGeometry.hxx | 25 +++----- simgear/scene/tgdb/TreeBin.cxx | 8 +++ 3 files changed, 52 insertions(+), 70 deletions(-) diff --git a/simgear/scene/tgdb/ShaderGeometry.cxx b/simgear/scene/tgdb/ShaderGeometry.cxx index a6a7c1ed..632555fc 100644 --- a/simgear/scene/tgdb/ShaderGeometry.cxx +++ b/simgear/scene/tgdb/ShaderGeometry.cxx @@ -25,35 +25,52 @@ #include "ShaderGeometry.hxx" +#include + using namespace osg; using namespace osgDB; namespace simgear { -void ShaderGeometry::drawImplementation(RenderInfo& renderInfo) const +void ShaderGeometry::addTree(const TreeBin::Tree& t) { - 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); + if (!getVertexArray()) { + setVertexData(_geometry->getVertexData()); + setNormalData(_geometry->getNormalData()); + setTexCoordData(0, _geometry->getTexCoordData(0)); + setColorArray(new Vec4Array()); + setColorBinding(Geometry::BIND_PER_PRIMITIVE_SET); + setVertexAttribArray(1, new FloatArray()); + setVertexAttribBinding(1, Geometry::BIND_PER_PRIMITIVE_SET); } + Geometry::PrimitiveSetList& modelSets = _geometry->getPrimitiveSetList(); + size_t numSets = modelSets.size(); + Vec4Array *colors = static_cast(getColorArray()); + FloatArray *vertexAttribs + = static_cast(getVertexAttribArray(1)); + colors->insert(colors->end(), numSets, Vec4(t.position.osg(), t.scale)); + vertexAttribs->insert(vertexAttribs->end(), numSets, + (float)t.texture_index / varieties); + _primitives.insert(_primitives.end(), modelSets.begin(), modelSets.end()); + dirtyDisplayList(); + dirtyBound(); } BoundingBox ShaderGeometry::computeBound() const { BoundingBox geom_box = _geometry->getBound(); BoundingBox bb; - for(TreeBin::TreeList::const_iterator itr = _trees.begin(); - itr != _trees.end(); - ++itr) { - 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() )); + unsigned numSets = _geometry->getNumPrimitiveSets(); + const Vec4Array* posScales = static_cast(getColorArray()); + if (!posScales) + return bb; + size_t numPosScales = posScales->size(); + for (int i = 0; i < numPosScales; i += numSets) { + const Vec4& posScale((*posScales)[i]); + const float scale = posScale.w(); + const Vec3 pos(posScale.x(), posScale.y(), posScale.z()); + for (unsigned j = 0; j < 7; ++j) + bb.expandBy(geom_box.corner(j) * scale + pos); } return bb; } @@ -67,34 +84,11 @@ bool ShaderGeometry_readLocalData(Object& obj, Input& fr) if ((fr[0].matchWord("geometry"))) { ++fr; iteratorAdvanced = true; - osg::Drawable* drawable = fr.readDrawable(); + osg::Geometry* drawable = dynamic_cast(fr.readDrawable()); if (drawable) { geom._geometry = drawable; } } - if ((fr.matchSequence("instances %i"))) { - int entry = fr[0].getNoNestedBrackets(); - int capacity; - fr[1].getInt(capacity); - geom._trees.reserve(capacity); - fr += 3; - iteratorAdvanced = true; - // skip { - while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) { - SGVec3f v; - int t; - float s; - if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y()) - && fr[2].getFloat(v.z()) && fr[3].getInt(t) && fr[4].getFloat(s)) { - fr += 4; - //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; - } - } - } return iteratorAdvanced; } @@ -104,18 +98,6 @@ bool ShaderGeometry_writeLocalData(const Object& obj, Output& fw) fw.indent() << "geometry" << std::endl; fw.writeObject(*geom._geometry); - fw.indent() << "instances " << geom._trees.size() << std::endl; - fw.indent() << "{" << std::endl; - fw.moveIn(); - for (TreeBin::TreeList::const_iterator iter - = geom._trees.begin(); - iter != geom._trees.end(); - ++iter) { - fw.indent() << iter->position.x() << " " << iter->position.y() << " " << iter->position.z() << " " - << iter->texture_index << " " << iter->scale << std::endl; - } - fw.moveOut(); - fw.indent() << "}" << std::endl; return true; } @@ -123,8 +105,9 @@ osgDB::RegisterDotOsgWrapperProxy shaderGeometryProxy ( new ShaderGeometry, "ShaderGeometry", - "Object Drawable ShaderGeometry", + "Object Drawable Geometry ShaderGeometry", &ShaderGeometry_readLocalData, &ShaderGeometry_writeLocalData ); } + diff --git a/simgear/scene/tgdb/ShaderGeometry.hxx b/simgear/scene/tgdb/ShaderGeometry.hxx index 9814af28..0044dd4e 100644 --- a/simgear/scene/tgdb/ShaderGeometry.hxx +++ b/simgear/scene/tgdb/ShaderGeometry.hxx @@ -37,45 +37,36 @@ namespace simgear { -class ShaderGeometry : public osg::Drawable +class ShaderGeometry : public osg::Geometry { public: - ShaderGeometry() + ShaderGeometry() : + varieties(1) { - 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) {} + osg::Geometry(ShaderGeometry,copyop) {} META_Object(flightgear, ShaderGeometry); - typedef std::vector PositionSizeList; - - virtual void drawImplementation(osg::RenderInfo& renderInfo) const; virtual osg::BoundingBox computeBound() const; - - void setGeometry(osg::Drawable* geometry) + void setGeometry(osg::Geometry* geometry) { _geometry = geometry; } - void addTree(TreeBin::Tree tree) - { - _trees.push_back(tree); - } - - osg::ref_ptr _geometry; + void addTree(const TreeBin::Tree& tree); + + osg::ref_ptr _geometry; - TreeBin::TreeList _trees; int varieties; protected: diff --git a/simgear/scene/tgdb/TreeBin.cxx b/simgear/scene/tgdb/TreeBin.cxx index b4219f33..1b3355dd 100644 --- a/simgear/scene/tgdb/TreeBin.cxx +++ b/simgear/scene/tgdb/TreeBin.cxx @@ -128,11 +128,17 @@ osg::Geometry* createOrthQuads(float w, float h, int varieties, const osg::Matri static char vertexShaderSource[] = "varying float fogFactor;\n" +#ifndef TSG_PACKED_ATTRIBUTES "attribute float textureIndex;\n" +#endif "\n" "void main(void)\n" "{\n" +#ifdef TSG_PACKED_ATTRIBUTES + " gl_TexCoord[0] = gl_MultiTexCoord0;\n" +#else " gl_TexCoord[0] = gl_MultiTexCoord0 + vec4(textureIndex, 0.0, 0.0, 0.0);\n" +#endif " 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" @@ -247,7 +253,9 @@ 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); +#ifndef TSG_PACKED_ATTRIBUTES program->addBindAttribLocation("textureIndex", 1); +#endif Shader* fragment_shader = new Shader(Shader::FRAGMENT, fragmentShaderSource); From f7dc7f039e20a7fa74a87a9e69eb1c463a4baf5d Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Fri, 23 Jan 2009 14:36:53 +0100 Subject: [PATCH 2/2] QuadTreeBuilder: create leaves on demand This avoids lots of empty leaves. --- simgear/scene/util/QuadTreeBuilder.hxx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/simgear/scene/util/QuadTreeBuilder.hxx b/simgear/scene/util/QuadTreeBuilder.hxx index 62734e3b..28d7cebd 100644 --- a/simgear/scene/util/QuadTreeBuilder.hxx +++ b/simgear/scene/util/QuadTreeBuilder.hxx @@ -42,12 +42,13 @@ public: const MakeLeaf& makeLeaf = MakeLeaf()) : _root(new osg::Group), _depth(depth), _dimension(1 << depth), _leafStorage(_dimension * _dimension), - _leaves(_leafStorage, _dimension), _getLocalCoords(getLocalCoords), + _leaves(_leafStorage, _dimension), + _leafParents(_leafParentStorage, _dimension / 2), + _getLocalCoords(getLocalCoords), _addLeafObject(addLeafObject), _makeLeaf(makeLeaf) { using namespace std; using namespace osg; - generate(_leafStorage.begin(), _leafStorage.end(), _makeLeaf); vector parentNodes(1); parentNodes[0] = _root.get(); unsigned leafDim = 2; @@ -63,11 +64,8 @@ public: } parentNodes.swap(interiorNodes); } - VectorArrayAdapter > leafParents(parentNodes, - _dimension / 2); - for (int j = 0; j < _dimension; ++j) - for (int k =0; k < _dimension; ++k) - leafParents(j / 2, k / 2)->addChild(_leaves(j, k)); + // Save leaf parents for later when we add leaves + _leafParentStorage = parentNodes; } osg::Vec2 getMin() { return _min; } void setMin(const osg::Vec2& min) { _min = min; } @@ -90,6 +88,10 @@ public: y = (int)(_dimension * (center.y() - _min.y()) / (_max.y() - _min.y())); y = clampTo(y, 0, (_dimension -1)); + if (!_leaves(y, x)) { + _leaves(y, x) = _makeLeaf(); + _leafParents(y / 2, x / 2)->addChild(_leaves(y, x)); + } _addLeafObject(_leaves(y, x), obj); } // STL craziness @@ -125,6 +127,8 @@ protected: int _dimension; LeafVector _leafStorage; VectorArrayAdapter _leaves; + std::vector _leafParentStorage; + VectorArrayAdapter > _leafParents; const GetObjectLocalCoords _getLocalCoords; const AddLeafObject _addLeafObject; const MakeLeaf _makeLeaf;