-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
This patch combines all the triangles, triangle strips and triangle fans
with the same material in a tile into one DrawElements primitive set.
This also reduces by a factor of 100 the number of Geodes that needs to
be processed by the cull phase.
On my machine I see a 1.5 ms decrease in cull and draw times and a .5ms
increase in "event" time, probably due to increased time in intersection
testing. I'll take a 1ms decrease in total frame time (9%) :)
Tim
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iD8DBQFGWG02eDhWHdXrDRURAlP4AKCEermb3De1Nt04N0uBTpzPKMRAkACgzu2/
wyxVgdDpZgrSmWO9OePmaAU=
=9NxH
-----END PGP SIGNATURE-----
Index: simgear/scene/tgdb/leaf.cxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/tgdb/leaf.cxx,v
retrieving revision 1.10
diff -d -u -r1.10 leaf.cxx
--- simgear/scene/tgdb/leaf.cxx 8 May 2007 06:11:15 -0000 1.10
+++ simgear/scene/tgdb/leaf.cxx 26 May 2007 16:55:18 -0000
@@ -97,7 +97,7 @@
}
};
-static void SGGenRandomSurfacePoints( osg::Geometry *leaf, double factor,
+void SGGenRandomSurfacePoints( osg::Geometry *leaf, double factor,
osg::Vec3Array *lights )
{
osg::TriangleFunctor<SGRandomSurfacePointsFill> triangleFunctor;
@@ -227,3 +227,160 @@
return geometry;
}
+// Specialization of triangle index production and DrawElements type.
+namespace {
+// Trick to turn integers (e.g., GL_TRIANGLES) into types
+template <int v>
+struct Int2Type
+{
+ enum { value = v };
+};
+
+// Triangles use the vertices in order.
+template <class DEType>
+void addIndices(int baseIndex, int numIndices, DEType* de,
+ Int2Type<GL_TRIANGLES>)
+{
+ typedef typename DEType::value_type ValueType;
+ for (int i = 0; i < numIndices; ++i) {
+ de->push_back((ValueType)(baseIndex + i));
+ }
+}
+
+// Duplicate the vertex "swapping" of triangle strips using the
+// indicies of the vertex data.
+template <class DEType>
+void addIndices(int baseIndex, int numIndices, DEType* de,
+ Int2Type<GL_TRIANGLE_STRIP>)
+{
+ typedef typename DEType::value_type ValueType;
+ int index = baseIndex;
+
+ for (int i = 2; i < numIndices; ++i, ++index) {
+ de->push_back((ValueType)(index));
+ if (i % 2) {
+ de->push_back((ValueType)(index + 2));
+ de->push_back((ValueType)(index + 1));
+ } else {
+ de->push_back((ValueType)(index + 1));
+ de->push_back((ValueType)(index + 2));
+ }
+ }
+}
+
+// And again for triangle fans.
+template <class DEType>
+void addIndices(int baseIndex, int numIndices, DEType* de,
+ Int2Type<GL_TRIANGLE_FAN>)
+{
+ typedef typename DEType::value_type ValueType;
+ int index = baseIndex + 1;
+ for (int i = 2; i < numIndices; ++i, ++index) {
+ de->push_back((ValueType)(baseIndex));
+ de->push_back((ValueType)(index));
+ de->push_back((ValueType)(index + 1));
+ }
+}
+
+template <class GeomType>
+void addIndicesToGeometry(int baseIndex, int numIndices,
+ osg::Geometry *geometry, GeomType)
+{
+ osg::PrimitiveSet* pset = geometry->getPrimitiveSet(0);
+ osg::DrawElementsUByte* db = dynamic_cast<osg::DrawElementsUByte*>(pset);
+ osg::DrawElementsUShort* ds = dynamic_cast<osg::DrawElementsUShort*>(pset);
+ osg::DrawElementsUInt* di = dynamic_cast<osg::DrawElementsUInt*>(pset);
+ if (db)
+ addIndices(baseIndex, numIndices, db, GeomType());
+ else if (ds)
+ addIndices(baseIndex, numIndices, ds, GeomType());
+ else
+ addIndices(baseIndex, numIndices, di, GeomType());
+}
+
+} // namespace
+
+// Add leaf geometry to an existing osg::Geometry which has a
+// DrawElements primitive set. The caller must guarantee that the
+// DrawElements type (UByte, UShort or Uint) is big enough to contain
+// the indices for the new triangles.
+void SGAddLeafToDrawable(osg::Geometry* geometry, const GLenum ty,
+ SGMaterial *mat,
+ const point_list& nodes, const point_list& normals,
+ const point_list& texcoords,
+ const int_list& node_index,
+ const int_list& normal_index,
+ const int_list& tex_index)
+{
+ double tex_width = 1000.0, tex_height = 1000.0;
+
+ if (mat) {
+ // set the texture width and height values for this
+ // material
+ tex_width = mat->get_xsize();
+ tex_height = mat->get_ysize();
+ }
+ osg::Vec3Array* vl
+ = static_cast<osg::Vec3Array*>(geometry->getVertexArray());
+ osg::Vec3Array* nl
+ = static_cast<osg::Vec3Array*>(geometry->getNormalArray());
+ osg::Vec2Array* tl
+ = static_cast<osg::Vec2Array*>(geometry->getTexCoordArray(0));
+ int baseIndex = vl->size();
+ int i;
+
+ // vertices
+ int size = node_index.size();
+ for ( i = 0; i < size; ++i ) {
+ Point3D node = nodes[ node_index[i] ];
+ vl->push_back(osg::Vec3(node[0], node[1], node[2]));
+ }
+ // normals
+ if ( normal_index.size() ) {
+ // object file specifies normal indices (i.e. normal indices
+ // aren't 'implied'
+ for ( i = 0; i < size; ++i ) {
+ Point3D normal = normals[ normal_index[i] ];
+ nl->push_back(osg::Vec3(normal[0], normal[1], normal[2]));
+ }
+ } else {
+ // use implied normal indices. normal index = vertex index.
+ for ( i = 0; i < size; ++i ) {
+ Point3D normal = normals[ node_index[i] ];
+ nl->push_back(osg::Vec3(normal[0], normal[1], normal[2]));
+ }
+ }
+ // texture coordinates
+ int tsize = tex_index.size();
+ Point3D texcoord;
+ if ( tsize == 1 ) {
+ SG_LOG( SG_TERRAIN, SG_ALERT, "Only 1 tex coord in leaf" );
+ Point3D texcoord = texcoords[ tex_index[0] ];
+ osg::Vec2 tmp2(texcoord[0], texcoord[1]);
+ if ( tex_width > 0 )
+ tmp2[0] *= (1000.0 / tex_width);
+ if ( tex_height > 0 )
+ tmp2[1] *= (1000.0 / tex_height);
+ for (i = 0; i < size; ++i)
+ tl->push_back(tmp2);
+ } else if ( size > 1 ) {
+ for ( i = 0; i < size; ++i ) {
+ Point3D texcoord = texcoords[ tex_index[i] ];
+ osg::Vec2 tmp2(texcoord[0], texcoord[1]);
+ if ( tex_width > 0 )
+ tmp2[0] *= (1000.0 / tex_width);
+ if ( tex_height > 0 )
+ tmp2[1] *= (1000.0 / tex_height);
+ tl ->push_back(tmp2);
+ }
+ }
+ if (ty == GL_TRIANGLES)
+ addIndicesToGeometry(baseIndex, size, geometry,
+ Int2Type<GL_TRIANGLES>());
+ else if (ty == GL_TRIANGLE_STRIP)
+ addIndicesToGeometry(baseIndex, size, geometry,
+ Int2Type<GL_TRIANGLE_STRIP>());
+ else
+ addIndicesToGeometry(baseIndex, size, geometry,
+ Int2Type<GL_TRIANGLE_FAN>());
+}
Index: simgear/scene/tgdb/leaf.hxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/tgdb/leaf.hxx,v
retrieving revision 1.7
diff -d -u -r1.7 leaf.hxx
--- simgear/scene/tgdb/leaf.hxx 8 May 2007 06:11:15 -0000 1.7
+++ simgear/scene/tgdb/leaf.hxx 26 May 2007 16:55:18 -0000
@@ -35,6 +35,8 @@
#include STL_STRING
#include <osg/Array>
+#include <osg/Drawable>
+#include <osg/Geometry>
#include <osg/Node>
#include <simgear/math/sg_types.hxx>
@@ -44,7 +46,8 @@
class SGMaterialLib; // forward declaration.
-
+void SGGenRandomSurfacePoints( osg::Geometry *leaf, double factor,
+ osg::Vec3Array *lights );
// Create a ssg leaf
osg::Drawable* SGMakeLeaf( const string& path,
const GLenum ty, SGMaterial *mat,
@@ -55,4 +58,10 @@
const int_list& tex_index,
const bool calc_lights, osg::Vec3Array *lights );
+void SGAddLeafToDrawable(osg::Geometry* geom, const GLenum ty, SGMaterial *mat,
+ const point_list& nodes, const point_list& normals,
+ const point_list& texcoords,
+ const int_list& node_index,
+ const int_list& normal_index,
+ const int_list& tex_index);
#endif // _SG_LEAF_HXX
Index: simgear/scene/tgdb/obj.cxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/tgdb/obj.cxx,v
retrieving revision 1.21
diff -d -u -r1.21 obj.cxx
--- simgear/scene/tgdb/obj.cxx 8 May 2007 06:11:15 -0000 1.21
+++ simgear/scene/tgdb/obj.cxx 26 May 2007 16:55:18 -0000
@@ -420,8 +420,7 @@
group_list::size_type i;
osg::Geode* geode = new osg::Geode;
- local_terrain->addChild( geode );
-
+
// generate points
string_list const& pt_materials = obj.get_pt_materials();
group_list const& pts_v = obj.get_pts_v();
@@ -507,52 +506,102 @@
while ( lmi != leafMap.end() ) {
SGMaterial *mat = findMaterial( lmi->first, path, matlib );
list<Leaf> &leaf_list = lmi->second;
+ int numTris = 0;
+ int numVerts = 0;
list<Leaf>::iterator li = leaf_list.begin();
- while ( li != leaf_list.end() ) {
+ // Count the total number of vertices so that the proper width
+ // osg::DrawElements class can be created to index them.
+ while (li != leaf_list.end()) {
+ Leaf &leaf = *li;
+ int vertSize = 0;
+ if (leaf.type == GL_TRIANGLES) {
+ vertSize = tris_v[leaf.index].size();
+ numTris += vertSize / 3;
+ } else if (leaf.type == GL_TRIANGLE_STRIP) {
+ vertSize = strips_v[leaf.index].size();
+ numTris += vertSize - 2;
+ } else {
+ vertSize = fans_v[leaf.index].size();
+ numTris += vertSize - 2;
+ }
+ numVerts += vertSize;
+ ++li;
+ }
+ // Allocate the drawable and its arrays.
+ osg::Geometry* geometry = new osg::Geometry;
+ osg::Vec3Array* vl = new osg::Vec3Array;
+ vl->reserve(numVerts);
+ geometry->setVertexArray(vl);
+ osg::Vec3Array* nl = new osg::Vec3Array;
+ nl->reserve(numVerts);
+ geometry->setNormalArray(nl);
+ geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+ osg::Vec2Array* tl = new osg::Vec2Array;
+ tl->reserve(numVerts);
+ geometry->setTexCoordArray(0, tl);
+ osg::Vec4Array* cl = new osg::Vec4Array;
+ cl->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+ geometry->setColorArray(cl);
+ geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ if (numVerts < 256) {
+ osg::DrawElementsUByte* db
+ = new osg::DrawElementsUByte(osg::PrimitiveSet::TRIANGLES);
+ db->reserve(numTris * 3);
+ geometry->addPrimitiveSet(db);
+ } else if (numVerts < 65536) {
+ osg::DrawElementsUShort* ds
+ = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES);
+ ds->reserve(numTris * 3);
+ geometry->addPrimitiveSet(ds);
+ } else {
+ osg::DrawElementsUInt* di
+ = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
+ di->reserve(numTris * 3);
+ geometry->addPrimitiveSet(di);
+ }
+ if (mat)
+ geometry->setStateSet(mat->get_state());
+ li = leaf_list.begin();
+ while ( li != leaf_list.end() ) {
Leaf &leaf = *li;
int ind = leaf.index;
if ( leaf.type == GL_TRIANGLES ) {
- osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLES, mat,
- nodes, normals, texcoords,
- tris_v[ind], tris_n[ind],
tris_tc[ind],
- is_base, ground_lights );
- if ( random_object_branch ) {
- if ( mat ) {
- gen_random_surface_objects( leaf, random_object_branch,
- ¢er, mat );
- }
- }
- geode->addDrawable( leaf );
+ SGAddLeafToDrawable(geometry, GL_TRIANGLES, mat,
+ nodes, normals, texcoords,
+ tris_v[ind], tris_n[ind], tris_tc[ind]);
} else if ( leaf.type == GL_TRIANGLE_STRIP ) {
- osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLE_STRIP, mat,
- nodes, normals, texcoords,
- strips_v[ind], strips_n[ind],
strips_tc[ind],
- is_base, ground_lights );
- if ( random_object_branch ) {
- if ( mat ) {
- gen_random_surface_objects( leaf, random_object_branch,
- ¢er, mat );
- }
- }
- geode->addDrawable( leaf );
+ SGAddLeafToDrawable(geometry, GL_TRIANGLE_STRIP, mat,
+ nodes, normals, texcoords,
+ strips_v[ind], strips_n[ind],
+ strips_tc[ind]);
} else {
- osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLE_FAN, mat,
- nodes, normals, texcoords,
- fans_v[ind], fans_n[ind],
fans_tc[ind],
- is_base, ground_lights );
- if ( random_object_branch ) {
- if ( mat ) {
- gen_random_surface_objects( leaf, random_object_branch,
- ¢er, mat );
- }
- }
- geode->addDrawable( leaf );
+ SGAddLeafToDrawable(geometry, GL_TRIANGLE_FAN, mat,
+ nodes, normals, texcoords,
+ fans_v[ind], fans_n[ind], fans_tc[ind]);
}
++li;
}
+ if ( random_object_branch ) {
+ if ( mat ) {
+ gen_random_surface_objects(geometry, random_object_branch,
+ ¢er, mat );
+ }
+ }
+ geode->addDrawable(geometry);
+ if (is_base && mat) {
+ float coverage = mat->get_light_coverage();
+ if ( coverage > 0.0 ) {
+ if ( coverage < 10000.0 ) {
+ SG_LOG(SG_INPUT, SG_ALERT, "Light coverage is "
+ << coverage << ", pushing up to 10000");
+ coverage = 10000;
+ }
+ SGGenRandomSurfacePoints(geometry, coverage, ground_lights);
+ }
+ }
++lmi;
}
-
+ local_terrain->addChild( geode );
return true;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel