1
0
Fork 0

Moved object information into a new subclass of FGNewMat, and changed

the property name from coverage to coverage_m2.
This commit is contained in:
david 2002-07-20 01:51:27 +00:00
parent e5f4da0e9a
commit cecedd302b
3 changed files with 141 additions and 72 deletions

View file

@ -90,6 +90,83 @@ local_file_exists( const string& path ) {
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGNewMat::Object.
////////////////////////////////////////////////////////////////////////
FGNewMat::Object::Object (const SGPropertyNode * node)
: _path(node->getStringValue("path")),
_model(0),
_coverage_m2(node->getDoubleValue("coverage-m2", 100000)),
_range_m(node->getDoubleValue("range-m", 2000))
{
string hdg = node->getStringValue("heading-type", "fixed");
if (hdg == "fixed") {
_heading_type = HEADING_FIXED;
} else if (hdg == "billboard") {
_heading_type = HEADING_BILLBOARD;
} else if (hdg == "random") {
_heading_type = HEADING_RANDOM;
} else {
_heading_type = HEADING_FIXED;
SG_LOG(SG_INPUT, SG_ALERT, "Unknown heading type: " << hdg
<< "; using 'fixed' instead.");
}
}
FGNewMat::Object::~Object ()
{
_model->deRef();
}
const string &
FGNewMat::Object::get_path () const
{
return _path;
}
ssgEntity *
FGNewMat::Object::get_model () const
{
// Load model only on demand
if (_model == 0) {
SGPath path = globals->get_fg_root();
path.append(_path);
ssgTexturePath((char *)path.dir().c_str());
ssgEntity * entity = load_object((char *)path.c_str());
if (entity != 0) {
float ranges[] = {0, _range_m};
_model = new ssgRangeSelector;
((ssgRangeSelector *)_model)->setRanges(ranges, 2);
if (_heading_type == HEADING_BILLBOARD) {
ssgCutout * cutout = new ssgCutout(false);
cutout->addKid(entity);
((ssgBranch *)_model)->addKid(cutout);
} else {
((ssgBranch *)_model)->addKid(entity);
}
_model->ref();
} else {
SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << path.str());
}
}
return _model;
}
double
FGNewMat::Object::get_coverage_m2 () const
{
return _coverage_m2;
}
double
FGNewMat::Object::get_range_m () const
{
return _range_m;
}
////////////////////////////////////////////////////////////////////////
// Constructors and destructor.
@ -118,8 +195,10 @@ FGNewMat::FGNewMat (ssgSimpleState * s)
FGNewMat::~FGNewMat (void)
{
for (unsigned int i = 0; i < objects.size(); i++)
objects[i].model->deRef();
for (unsigned int i = 0; i < objects.size(); i++) {
delete objects[i];
objects[i] = 0;
}
}
@ -174,33 +253,10 @@ FGNewMat::read_properties (const SGPropertyNode * props)
((SGPropertyNode *)props)->getChildren("object");
for (unsigned int i = 0; i < object_nodes.size(); i++) {
const SGPropertyNode * object_node = object_nodes[i];
if (object_node->hasChild("path")) {
Object object;
SGPath path = globals->get_fg_root();
path.append(object_node->getStringValue("path"));
ssgTexturePath((char *)path.dir().c_str());
ssgEntity * model = load_object((char *)path.c_str());
if (model != 0) {
float ranges[] = {0, object_node->getDoubleValue("range-m", 2000)};
object.model = new ssgRangeSelector;
((ssgRangeSelector *)object.model)->setRanges(ranges, 2);
if (object_node->getBoolValue("billboard", false)) {
ssgCutout * cutout = new ssgCutout(false);
cutout->addKid(model);
((ssgBranch *)object.model)->addKid(cutout);
} else {
((ssgBranch *)object.model)->addKid(model);
}
object.model->ref();
object.coverage = object_node->getDoubleValue("coverage", 100000);
object.lod = object_node->getDoubleValue("range-m", 2000);
objects.push_back(object);
} else {
SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << path.str());
}
} else {
if (object_node->hasChild("path"))
objects.push_back(new Object(object_node));
else
SG_LOG(SG_INPUT, SG_ALERT, "No path supplied for object");
}
}
}

View file

@ -64,6 +64,43 @@ class FGNewMat {
public:
//////////////////////////////////////////////////////////////////////
// Inner class.
//////////////////////////////////////////////////////////////////////
/**
* A randomly-placeable object.
*/
class Object
{
public:
enum HeadingType {
HEADING_FIXED,
HEADING_BILLBOARD,
HEADING_RANDOM
};
const string &get_path () const;
ssgEntity * get_model () const;
double get_coverage_m2 () const;
double get_range_m () const;
HeadingType get_heading_type () const;
protected:
friend class FGNewMat;
Object (const SGPropertyNode * node);
virtual ~Object ();
private:
string _path;
mutable ssgEntity * _model;
double _coverage_m2;
double _range_m;
HeadingType _heading_type;
};
////////////////////////////////////////////////////////////////////
// Public Constructors.
@ -148,31 +185,15 @@ public:
/**
* Get the number of dynamic objects defined for this material.
* Get the number of randomly-placed objects defined for this material.
*/
virtual int get_object_count () const { return objects.size(); }
/**
* Get a dynamic object for this material.
* Get a randomly-placed object for this material.
*/
virtual ssgEntity * get_object (int i) const { return objects[i].model; }
/**
* Get the average space for a dynamic object for this material.
*/
virtual double get_object_coverage (int i) const {
return objects[i].coverage;
}
/**
* Get the target LOD range for a dynamic object for this material.
*/
virtual double get_object_lod (int i) const {
return objects[i].lod;
}
virtual Object * get_object (int index) const { return objects[index]; }
/**
@ -249,14 +270,7 @@ private:
// true if texture loading deferred, and not yet loaded
bool texture_loaded;
struct Object
{
ssgEntity * model;
double coverage;
double lod;
};
vector<Object> objects;
vector<Object *> objects;
// ref count so we can properly delete if we have multiple
// pointers to this record
@ -274,6 +288,7 @@ private:
void build_ssg_state(bool defer_tex_load = false);
void set_ssg_state( ssgSimpleState *s );
};
#endif // _NEWMAT_HXX

View file

@ -329,7 +329,7 @@ static void gen_random_surface_points( ssgLeaf *leaf, ssgVertexArray *lights,
*/
static void
add_object_to_triangle (sgVec3 p1, sgVec3 p2, sgVec3 p3, sgVec3 center,
sgMat4 ROT, FGNewMat * mat, int object_index,
sgMat4 ROT, FGNewMat::Object * object,
ssgBranch * branch)
{
sgVec3 result;
@ -342,7 +342,7 @@ add_object_to_triangle (sgVec3 p1, sgVec3 p2, sgVec3 p3, sgVec3 center,
sgPostMultMat4(OBJ, OBJ_pos);
ssgTransform * pos = new ssgTransform;
pos->setTransform(OBJ);
pos->addKid(mat->get_object(object_index));
pos->addKid(object->get_model());
branch->addKid(pos);
}
@ -353,8 +353,7 @@ public:
float * p1;
float * p2;
float * p3;
FGNewMat * mat;
int object_index;
FGNewMat::Object * object;
ssgBranch * branch;
sgMat4 ROT;
};
@ -376,8 +375,8 @@ public:
* surface.
*/
static void
fill_in_triangle (float * p1, float * p2, float * p3, FGNewMat * mat,
int object_index, ssgBranch * branch, sgMat4 ROT)
fill_in_triangle (float * p1, float * p2, float * p3,
FGNewMat::Object *object, ssgBranch * branch, sgMat4 ROT)
{
sgVec3 center;
sgSetVec3(center,
@ -385,12 +384,11 @@ fill_in_triangle (float * p1, float * p2, float * p3, FGNewMat * mat,
(p1[1] + p2[1] + p3[1]) / 3.0,
(p1[2] + p2[2] + p3[2]) / 3.0);
double area = sgTriArea(p1, p2, p3);
double num = area / mat->get_object_coverage(object_index);
double num = area / object->get_coverage_m2();
// place an object each unit of area
while ( num > 1.0 ) {
add_object_to_triangle(p1, p2, p3, center,
ROT, mat, object_index, branch);
add_object_to_triangle(p1, p2, p3, center, ROT, object, branch);
num -= 1.0;
}
// for partial units of area, use a zombie door method to
@ -399,8 +397,7 @@ fill_in_triangle (float * p1, float * p2, float * p3, FGNewMat * mat,
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, object_index, branch);
add_object_to_triangle(p1, p2, p3, center, ROT, object, branch);
}
}
}
@ -423,8 +420,8 @@ in_range_callback (ssgEntity * entity, int mask)
{
RandomObjectUserData * data = (RandomObjectUserData *)entity->getUserData();
if (!data->is_filled_in) {
fill_in_triangle(data->p1, data->p2, data->p3, data->mat,
data->object_index, data->branch, data->ROT);
fill_in_triangle(data->p1, data->p2, data->p3, data->object,
data->branch, data->ROT);
data->is_filled_in = true;
}
return 1;
@ -540,7 +537,7 @@ get_bounding_radius (sgVec3 center, float *p1, float *p2, float *p3)
*/
static void
setup_triangle (float * p1, float * p2, float * p3,
FGNewMat * mat, ssgBranch * branch, sgMat4 ROT)
FGNewMat * mat, ssgBranch * branch, sgMat4 ROT)
{
// Set up a single center point for LOD
sgVec3 center;
@ -564,13 +561,15 @@ setup_triangle (float * p1, float * p2, float * p3,
// Iterate through all the object types.
int num_objects = mat->get_object_count();
for (int i = 0; i < num_objects; i++) {
// Look up the random object.
FGNewMat::Object * object = mat->get_object(i);
// Set up the range selector for the entire
// triangle; note that we use the object
// range plus the bounding radius here, to
// allow for objects far from the center.
float ranges[] = {0,
mat->get_object_lod(i) + bounding_radius,
object->get_range_m() + bounding_radius,
500000};
ssgRangeSelector * lod = new ssgRangeSelector;
lod->setRanges(ranges, 3);
@ -589,8 +588,7 @@ setup_triangle (float * p1, float * p2, float * p3,
data->p1 = p1;
data->p2 = p2;
data->p3 = p3;
data->mat = mat;
data->object_index = i;
data->object = object;
data->branch = in_range;
sgCopyMat4(data->ROT, ROT);