Melchior FRANZ:

here is the promised material animation. It looks a bit longish, but that
wasn't avoidable -- there are simply too many parameters to consider. I tried
hard, though, to make the animation fast by only doing the necessary stuff.
It doesn't affect the frame rate here with my test model. The animation is
heavily based on Jim's "material-emission" animation.

* implementation of the "material" animation (this required to make the
  texture path available) + documentation update ($FG_ROOT/Docs/)
* fix some more return values (texture animations, and select) for the
  shadow problem (and some in anticipation of other problems  :-)
* fix compiler warning
This commit is contained in:
ehofman
2005-03-22 13:12:51 +00:00
parent 61a2e0f104
commit 3ce0c17237
4 changed files with 374 additions and 97 deletions

View File

@@ -339,7 +339,7 @@ SGSelectAnimation::update()
((ssgSelector *)_branch)->select(0xffff);
else
((ssgSelector *)_branch)->select(0x0000);
return 1;
return 2;
}
@@ -905,7 +905,7 @@ SGTexRotateAnimation::update()
}
set_rotation(_matrix, _position_deg, _center, _axis);
((ssgTexTrans *)_branch)->setTransform(_matrix);
return 1;
return 2;
}
@@ -953,7 +953,7 @@ SGTexTranslateAnimation::update()
}
set_translation(_matrix, _position, _axis);
((ssgTexTrans *)_branch)->setTransform(_matrix);
return 1;
return 2;
}
@@ -1070,7 +1070,7 @@ SGTexMultipleAnimation::update()
}
}
((ssgTexTrans *)_branch)->setTransform(tmatrix);
return 1;
return 2;
}
@@ -1112,95 +1112,308 @@ void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
////////////////////////////////////////////////////////////////////////
// Implementation of SGEmissionAnimation
// Implementation of SGMaterialAnimation
////////////////////////////////////////////////////////////////////////
SGEmissionAnimation::SGEmissionAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props)
: SGAnimation(props, new ssgBranch),
_prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
_color0(props->getFloatValue("emiss-red", 0.0)),
_color1(props->getFloatValue("emiss-green", 0.0)),
_color2(props->getFloatValue("emiss-blue", 0.0)),
_old_brightness(0.0),
_cached_material(0),
_cloned_material(0)
SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
SGPropertyNode_ptr props, const SGPath &texture_path)
: SGAnimation(props, new ssgBranch),
_base_dir(texture_path),
_cached_material(0),
_cloned_material(0),
_read(0),
_update(0),
_global(props->getBoolValue("global", false))
{
_diff.red = props->getFloatValue("diffuse-red", -1.0);
_diff.green = props->getFloatValue("diffuse-green", -1.0);
_diff.blue = props->getFloatValue("diffuse-blue", -1.0);
_diff.factor = props->getFloatValue("diffuse-factor", 1.0);
_diff.offset = props->getFloatValue("diffuse-offset", 0.0);
if (_diff.dirty())
_update |= DIFFUSE;
_amb.red = props->getFloatValue("ambient-red", -1.0);
_amb.green = props->getFloatValue("ambient-green", -1.0);
_amb.blue = props->getFloatValue("ambient-blue", -1.0);
_amb.factor = props->getFloatValue("ambient-factor", 1.0);
_amb.offset = props->getFloatValue("ambient-offset", 0.0);
if (_amb.dirty())
_update |= AMBIENT;
_spec.red = props->getFloatValue("specular-red", -1.0);
_spec.green = props->getFloatValue("specular-green", -1.0);
_spec.blue = props->getFloatValue("specular-blue", -1.0);
_spec.factor = props->getFloatValue("specular-factor", 1.0);
_spec.offset = props->getFloatValue("specular-offset", 0.0);
if (_spec.dirty())
_update |= SPECULAR;
_emis.red = props->getFloatValue("emission-red", -1.0);
_emis.green = props->getFloatValue("emission-green", -1.0);
_emis.blue = props->getFloatValue("emission-blue", -1.0);
_emis.factor = props->getFloatValue("emission-factor", 1.0);
_emis.offset = props->getFloatValue("emission-offset", 0.0);
if (_emis.dirty())
_update |= EMISSION;
_shi = props->getFloatValue("shininess", -1.0);
if (_shi >= 0.0)
_update |= SHININESS;
_trans = props->getFloatValue("transparency", -1.0);
if (_trans >= 0.0)
_update |= TRANSPARENCY;
_thresh = props->getFloatValue("threshold", -1.0);
if (_thresh >= 0.0)
_update |= THRESHOLD;
string _texture_str = props->getStringValue("texture", "");
if (!_texture_str.empty()) {
_texture = _base_dir;
_texture.append(_texture_str);
_update |= TEXTURE;
}
SGPropertyNode_ptr node = props->getChild("condition");
_condition = node ? sgReadCondition(prop_root, node) : 0;
node = props->getChild("diffuse-red-prop");
_diff.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("diffuse-green-prop");
_diff.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("diffuse-blue-prop");
_diff.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("diffuse-factor-prop");
_diff.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("diffuse-offset-prop");
_diff.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
if (_diff.live())
_read |= DIFFUSE;
node = props->getChild("ambient-red-prop");
_amb.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("ambient-green-prop");
_amb.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("ambient-blue-prop");
_amb.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("ambient-factor-prop");
_amb.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("ambient-offset-prop");
_amb.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
if (_amb.live())
_read |= AMBIENT;
node = props->getChild("specular-red-prop");
_spec.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("specular-green-prop");
_spec.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("specular-blue-prop");
_spec.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("specular-factor-prop");
_spec.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("specular-offset-prop");
_spec.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
if (_spec.live())
_read |= SPECULAR;
node = props->getChild("emission-red-prop");
_emis.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("emission-green-prop");
_emis.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("emission-blue-prop");
_emis.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("emission-factor-prop");
_emis.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("emission-offset-prop");
_emis.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
if (_emis.live())
_read |= EMISSION;
node = props->getChild("shininess-prop");
_shi_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("transparency-prop");
_trans_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("threshold-prop");
_thresh_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
node = props->getChild("texture-prop");
_tex_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
}
SGEmissionAnimation::~SGEmissionAnimation ()
void SGMaterialAnimation::init()
{
if (!_global)
cloneMaterials(_branch);
}
void SGEmissionAnimation::init()
int SGMaterialAnimation::update()
{
// clone material state(s) for this branch
cloneMaterials(_branch);
}
if (_condition && !_condition->test())
return 2;
void SGEmissionAnimation::cloneMaterials(ssgBranch *b)
{
// clone material state(s) for this branch
int nb = b->getNumKids();
// Traverse the branch(es) and make clones of material settings for the leaves on
// this branch (ssgSimpleState objects).
// Try to be efficient (only make a new clone if the original is different
// than the previous).
for (int i = 0; i<nb; i++) {
ssgEntity *e = b->getKid(i);
if (e->isAKindOf(ssgTypeLeaf())) {
ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
// if this is a new material state, then make a copy of it...
if (!_cached_material || _cached_material != s) {
_cached_material = s;
_cloned_material = (ssgSimpleState*)s->clone(SSG_CLONE_STATE);
if (_read & DIFFUSE) {
ColorSpec tmp = _diff;
if (_diff.red_prop)
_diff.red = _diff.red_prop->getFloatValue();
if (_diff.green_prop)
_diff.green = _diff.green_prop->getFloatValue();
if (_diff.blue_prop)
_diff.blue = _diff.blue_prop->getFloatValue();
if (_diff.factor_prop)
_diff.factor = _diff.factor_prop->getFloatValue();
if (_diff.offset_prop)
_diff.offset = _diff.offset_prop->getFloatValue();
if (_diff != tmp)
_update |= DIFFUSE;
}
if (_read & AMBIENT) {
ColorSpec tmp = _amb;
if (_amb.red_prop)
_amb.red = _amb.red_prop->getFloatValue();
if (_amb.green_prop)
_amb.green = _amb.green_prop->getFloatValue();
if (_amb.blue_prop)
_amb.blue = _amb.blue_prop->getFloatValue();
if (_amb.factor_prop)
_amb.factor = _amb.factor_prop->getFloatValue();
if (_amb.offset_prop)
_amb.offset = _amb.offset_prop->getFloatValue();
if (_amb != tmp)
_update |= AMBIENT;
}
if (_read & SPECULAR) {
ColorSpec tmp = _spec;
if (_spec.red_prop)
_spec.red = _spec.red_prop->getFloatValue();
if (_spec.green_prop)
_spec.green = _spec.green_prop->getFloatValue();
if (_spec.blue_prop)
_spec.blue = _spec.blue_prop->getFloatValue();
if (_spec.factor_prop)
_spec.factor = _spec.factor_prop->getFloatValue();
if (_spec.offset_prop)
_spec.offset = _spec.offset_prop->getFloatValue();
if (_spec != tmp)
_update |= SPECULAR;
}
if (_read & EMISSION) {
ColorSpec tmp = _emis;
if (_emis.red_prop)
_emis.red = _emis.red_prop->getFloatValue();
if (_emis.green_prop)
_emis.green = _emis.green_prop->getFloatValue();
if (_emis.blue_prop)
_emis.blue = _emis.blue_prop->getFloatValue();
if (_emis.factor_prop)
_emis.factor = _emis.factor_prop->getFloatValue();
if (_emis.offset_prop)
_emis.offset = _emis.offset_prop->getFloatValue();
if (_emis != tmp)
_update |= EMISSION;
}
float f;
if (_shi_prop) {
f = _shi;
_shi = _shi_prop->getFloatValue();
if (_shi != f)
_update |= SHININESS;
}
if (_trans_prop) {
f = _trans;
_trans = _trans_prop->getFloatValue();
if (_trans != f)
_update |= TRANSPARENCY;
}
if (_thresh_prop) {
f = _thresh;
_thresh = _thresh_prop->getFloatValue();
if (_thresh != f)
_update |= THRESHOLD;
}
if (_tex_prop) {
string t = _tex_prop->getStringValue();
if (!t.empty() && t != _texture_str) {
_texture_str = t;
_texture = _base_dir;
_texture.append(t);
_update |= TEXTURE;
}
// set the material to the clone...
((ssgLeaf*)e)->setState( _cloned_material );
} else if (e->isAKindOf(ssgTypeBranch())) {
cloneMaterials( (ssgBranch*)e );
}
}
}
int SGEmissionAnimation::update()
{
float brightness = _prop->getFloatValue();
// clamp brightness 0 ~ 1
if (brightness < 0.00) brightness = 0.00;
if (brightness > 1.00) brightness = 1.00;
// no need to update states unless something changes...
if (brightness != _old_brightness) {
_old_brightness = brightness; // save it
float rd,gr,bl;
rd = _color0 * brightness;
gr = _color1 * brightness;
bl = _color2 * brightness;
setEmissionBranch(_branch, rd, gr, bl);
}
return 1;
}
void SGEmissionAnimation::setEmissionBranch(ssgBranch *b, float color0, float color1, float color2)
{
int nb = b->getNumKids();
for (int i = 0; i<nb; i++) {
ssgEntity *e = b->getKid(i);
if (e->isAKindOf(ssgTypeLeaf())) {
ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
s->setMaterial( GL_EMISSION, color0, color1, color2, 0.0 );
} else if (e->isAKindOf(ssgTypeBranch())) {
setEmissionBranch((ssgBranch*)e, color0, color1, color2);
if (_update) {
setMaterialBranch(_branch);
_update = 0;
}
}
return 2;
}
void SGMaterialAnimation::cloneMaterials(ssgBranch *b)
{
for (int i = 0; i < b->getNumKids(); i++)
cloneMaterials((ssgBranch *)b->getKid(i));
if (!b->isAKindOf(ssgTypeLeaf()) || !((ssgLeaf *)b)->hasState())
return;
ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
if (!_cached_material || _cached_material != s) {
_cached_material = s;
_cloned_material = (ssgSimpleState *)s->clone(SSG_CLONE_STATE);
}
((ssgLeaf *)b)->setState(_cloned_material);
}
void SGMaterialAnimation::setMaterialBranch(ssgBranch *b)
{
for (int i = 0; i < b->getNumKids(); i++)
setMaterialBranch((ssgBranch *)b->getKid(i));
if (!b->isAKindOf(ssgTypeLeaf()) || !((ssgLeaf *)b)->hasState())
return;
ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
s->disable(GL_COLOR_MATERIAL);
s->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
if (_update & DIFFUSE) {
float *v = _diff.rgba();
SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], alpha);
}
if (_update & AMBIENT)
s->setMaterial(GL_AMBIENT, _amb.rgba());
if (_update & SPECULAR)
s->setMaterial(GL_SPECULAR, _spec.rgba());
if (_update & EMISSION)
s->setMaterial(GL_EMISSION, _emis.rgba());
if (_update & SHININESS)
s->setShininess(clamp(_shi, 0.0, 128.0));
if (_update & TRANSPARENCY) {
SGfloat *v = s->getMaterial(GL_DIFFUSE);
s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], 1.0 - clamp(_trans));
}
if (_update & THRESHOLD)
s->setAlphaClamp(clamp(_thresh));
if (_update & TEXTURE)
s->setTexture(_texture.c_str());
if (_update & (TEXTURE|TRANSPARENCY)) {
SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
ssgTexture *tex = s->getTexture();
if ((tex && tex->hasAlpha()) || alpha < 0.999) {
s->enable(GL_BLEND);
s->enable(GL_ALPHA_TEST);
s->setTranslucent();
} else {
s->disable(GL_BLEND);
s->disable(GL_ALPHA_TEST);
s->setOpaque();
}
}
s->force();
}
////////////////////////////////////////////////////////////////////////
// Implementation of SGFlashAnimation
////////////////////////////////////////////////////////////////////////

View File

@@ -22,6 +22,7 @@ SG_USING_STD(map);
#include <simgear/math/point3d.hxx>
#include <simgear/props/props.hxx>
#include <simgear/misc/sg_path.hxx>
// Don't pull in the headers, since we don't need them here.
@@ -434,25 +435,86 @@ private:
/**
* An "animation" to modify emissive values on leaf nodes
* An "animation" to modify material properties
*/
class SGEmissionAnimation : public SGAnimation
class SGMaterialAnimation : public SGAnimation
{
public:
SGEmissionAnimation(SGPropertyNode *prop_root, SGPropertyNode_ptr props);
virtual ~SGEmissionAnimation ();
virtual void init();
virtual int update();
SGMaterialAnimation(SGPropertyNode *prop_root, SGPropertyNode_ptr props,
const SGPath &texpath);
virtual ~SGMaterialAnimation() {}
virtual void init();
virtual int update();
private:
SGPropertyNode_ptr _prop;
ssgSimpleState* _cached_material;
ssgSimpleState* _cloned_material;
void cloneMaterials(ssgBranch *b);
void setEmissionBranch(ssgBranch *b, float color0, float color1, float color2);
float _color0;
float _color1;
float _color2;
float _old_brightness;
enum {
DIFFUSE = 1,
AMBIENT = 2,
SPECULAR = 4,
EMISSION = 8,
SHININESS = 16,
TRANSPARENCY = 32,
THRESHOLD = 64,
TEXTURE = 128,
};
struct ColorSpec {
float red, green, blue;
float factor;
float offset;
SGPropertyNode_ptr red_prop;
SGPropertyNode_ptr green_prop;
SGPropertyNode_ptr blue_prop;
SGPropertyNode_ptr factor_prop;
SGPropertyNode_ptr offset_prop;
sgVec4 v;
bool dirty() {
return red >= 0.0 || green >= 0.0 || blue >= 0.0;
}
bool live() {
return red_prop || green_prop || blue_prop
|| factor_prop || offset_prop;
}
bool operator!=(ColorSpec& a) {
return red != a.red || green != a.green || blue != a.blue
|| factor != a.factor || offset != a.offset;
}
sgVec4 &rgba() {
v[0] = clamp(red * factor + offset);
v[1] = clamp(green * factor + offset);
v[2] = clamp(blue * factor + offset);
v[3] = 1.0;
return v;
}
float clamp(float val) {
return val < 0.0 ? 0.0 : val > 1.0 ? 1.0 : val;
}
};
SGCondition *_condition;
SGPath _base_dir;
SGPath _texture;
string _texture_str;
ssgSimpleState* _cached_material;
ssgSimpleState* _cloned_material;
unsigned _read;
unsigned _update;
bool _global;
ColorSpec _diff;
ColorSpec _amb;
ColorSpec _emis;
ColorSpec _spec;
float _shi;
float _trans;
float _thresh; // alpha_clamp (see man glAlphaFunc)
string _tex;
SGPropertyNode_ptr _shi_prop;
SGPropertyNode_ptr _trans_prop;
SGPropertyNode_ptr _thresh_prop;
SGPropertyNode_ptr _tex_prop;
void cloneMaterials(ssgBranch *b);
void setMaterialBranch(ssgBranch *b);
float clamp(float val, float min = 0.0, float max = 1.0) {
return val < min ? min : val > max ? max : val;
}
};

View File

@@ -19,7 +19,6 @@
#include <plib/ul.h>
#include <simgear/structure/exception.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
@@ -125,6 +124,7 @@ sgMakeAnimation( ssgBranch * model,
SGPropertyNode *prop_root,
SGPropertyNode_ptr node,
double sim_time_sec,
SGPath &texture_path,
set<ssgBranch *> &ignore_branches )
{
bool ignore = false;
@@ -159,8 +159,8 @@ sgMakeAnimation( ssgBranch * model,
ignore = true;
} else if (!strcmp("alpha-test", type)) {
animation = new SGAlphaTestAnimation(node);
} else if (!strcmp("material-emission", type)) {
animation = new SGEmissionAnimation(prop_root, node);
} else if (!strcmp("material", type)) {
animation = new SGMaterialAnimation(prop_root, node, texture_path);
} else if (!strcmp("flash", type)) {
animation = new SGFlashAnimation(node);
} else if (!strcmp("dist-scale", type)) {
@@ -327,7 +327,7 @@ sgLoad3DModel( const string &fg_root, const string &path,
vector<SGPropertyNode_ptr> name_nodes =
animation_nodes[i]->getChildren("object-name");
sgMakeAnimation( model, name, name_nodes, prop_root, animation_nodes[i],
sim_time_sec, ignore_branches);
sim_time_sec, texturepath, ignore_branches);
}
#if PLIB_VERSION > 183

View File

@@ -19,6 +19,7 @@ SG_USING_STD(set);
#include <plib/sg.h>
#include <plib/ssg.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
@@ -66,6 +67,7 @@ sgMakeAnimation( ssgBranch * model,
SGPropertyNode *prop_root,
SGPropertyNode_ptr node,
double sim_time_sec,
SGPath &texture_path,
set<ssgBranch *> &ignore_branches );
/**