From cc8567ad63f7d3eb86c7ec4b60ba41b57afc6fbd Mon Sep 17 00:00:00 2001 From: david Date: Wed, 17 Jul 2002 22:11:13 +0000 Subject: [PATCH] More functional decomposition and documentation. --- src/Objects/obj.cxx | 149 +++++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 56 deletions(-) diff --git a/src/Objects/obj.cxx b/src/Objects/obj.cxx index a3ca51c92..2f2a140a0 100644 --- a/src/Objects/obj.cxx +++ b/src/Objects/obj.cxx @@ -347,6 +347,77 @@ add_object_to_triangle (sgVec3 p1, sgVec3 p2, sgVec3 p3, sgVec3 center, } +/** + * Populate a single triangle with randomly-placed objects. + * + * The objects and their density are defined in the material. If the + * density is smaller than the minimum, there is an appropriate chance + * of one appearing. The ssgBranch supplied will be populated + * with the randomly-placed objects, with all objects of each type + * under a range selector. + * + * @param leaf The leaf containing the data for the terrain surface. + * @param tri_index The index of the triangle in the leaf. + * @param mat The material data for the triangle. + * @param branch The branch to which the randomly-placed objects + * should be added. + * @param ROT A rotation matrix to align the objects with the earth's + * surface at the current lat/lon. + */ +static void +populate_triangle (float * p1, float * p2, float * p3, + FGNewMat * mat, ssgBranch * branch, sgMat4 ROT) +{ + // Calculate the triangle area. + double area = sgTriArea(p1, p2, p3); + + // Set up a single center point for LOD + sgVec3 center; + sgSetVec3(center, + (p1[0] + p2[0] + p3[0]) / 3.0, + (p1[1] + p2[1] + p3[1]) / 3.0, + (p1[2] + p2[2] + p3[2]) / 3.0); + + // Set up a transformation to the center + // point, so that everything else can + // be specified relative to it. + ssgTransform * location = new ssgTransform; + sgMat4 TRANS; + sgMakeTransMat4(TRANS, center); + location->setTransform(TRANS); + branch->addKid(location); + + // Iterate through all the objects types. + int num_objects = mat->get_object_count(); + for (int i = 0; i < num_objects; i++) { + double num = area / mat->get_object_coverage(i); + float ranges[] = {0, mat->get_object_lod(i)}; + ssgRangeSelector * lod = new ssgRangeSelector; + lod->setRanges(ranges, 2); + location->addKid(lod); + ssgBranch * objects = new ssgBranch; + lod->addKid(objects); + + // place an object each unit of area + while ( num > 1.0 ) { + add_object_to_triangle(p1, p2, p3, center, + ROT, mat, i, objects); + num -= 1.0; + } + // for partial units of area, use a zombie door method to + // create the proper random chance of an object being created + // for this triangle + if ( num > 0.0 ) { + if ( sg_random() <= num ) { + // a zombie made it through our door + add_object_to_triangle(p1, p2, p3, center, + ROT, mat, i, objects); + } + } + } +} + + /** * Create a rotation matrix to align an object for the current lat/lon. * @@ -379,6 +450,20 @@ makeWorldUpRotationMatrix (sgMat4 ROT, double hdg_deg, } +/** + * Randomly place objects on a surface. + * + * The leaf node provides the geometry of the surface, while the + * material provides the objects and placement density. Latitude + * and longitude are required so that the objects can be rotated + * to the world-up vector. + * + * @param leaf The surface where the objects should be placed. + * @param branch The branch that will hold the randomly-placed objects. + * @param lon_deg The longitude of the surface center, in degrees. + * @param lat_deg The latitude of the surface center, in degrees. + * @param material_name The name of the surface's material. + */ static void gen_random_surface_objects (ssgLeaf *leaf, ssgBranch *branch, @@ -414,66 +499,18 @@ gen_random_surface_objects (ssgLeaf *leaf, sgMat4 ROT; makeWorldUpRotationMatrix(ROT, hdg_deg, lon_deg, lat_deg); - short int n1, n2, n3; - float *p1, *p2, *p3; - sgVec3 result; - // generate a repeatable random seed - p1 = leaf->getVertex( 0 ); - unsigned int seed = (unsigned int)p1[0]; - sg_srandom( seed ); + sg_srandom((unsigned int)(leaf->getVertex(0)[0])); // Iterate through all the triangles + // and populate them. for ( int i = 0; i < num_tris; ++i ) { - leaf->getTriangle( i, &n1, &n2, &n3 ); - p1 = leaf->getVertex(n1); - p2 = leaf->getVertex(n2); - p3 = leaf->getVertex(n3); - double area = sgTriArea( p1, p2, p3 ); - - // Set up a single center point for LOD - sgVec3 center; - sgSetVec3(center, - (p1[0] + p2[0] + p3[0]) / 3.0, - (p1[1] + p2[1] + p3[1]) / 3.0, - (p1[2] + p2[2] + p3[2]) / 3.0); - - // Set up a transformation to the center - // point, so that everything else can - // be specified relative to it. - ssgTransform * location = new ssgTransform; - sgMat4 TRANS; - sgMakeTransMat4(TRANS, center); - location->setTransform(TRANS); - branch->addKid(location); - - // Iterate through all the objects. - for (int j = 0; j < num_objects; j++) { - double num = area / mat->get_object_coverage(j); - float ranges[] = {0, mat->get_object_lod(j)}; - ssgRangeSelector * lod = new ssgRangeSelector; - lod->setRanges(ranges, 2); - location->addKid(lod); - ssgBranch * objects = new ssgBranch; - lod->addKid(objects); - - // place an object each unit of area - while ( num > 1.0 ) { - add_object_to_triangle(p1, p2, p3, center, - ROT, mat, j, objects); - num -= 1.0; - } - // for partial units of area, use a zombie door method to - // create the proper random chance of an object being created - // for this triangle - if ( num > 0.0 ) { - if ( sg_random() <= num ) { - // a zombie made it through our door - add_object_to_triangle(p1, p2, p3, center, - ROT, mat, j, objects); - } - } - } + short n1, n2, n3; + leaf->getTriangle(i, &n1, &n2, &n3); + populate_triangle(leaf->getVertex(n1), + leaf->getVertex(n2), + leaf->getVertex(n3), + mat, branch, ROT); } } -- 2.39.5