X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fmodel.cxx;h=edb91f27a8e1bae88fc28c3072f612d530b899a2;hb=f72b3882c36c83f3f83c9523a82f7d0c5ed519da;hp=96ebebaa1846e2dd5c9652ae7e932f0f929a9580;hpb=3d43bc04801e9c3b54d298a031467971cd0d3366;p=simgear.git diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 96ebebaa..edb91f27 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -7,18 +7,16 @@ #include #endif -#include - #include // for strcmp() #include +#include #include #include #include #include -#include #include #include @@ -26,21 +24,44 @@ #include "model.hxx" SG_USING_STD(vector); +SG_USING_STD(set); +bool sgUseDisplayList = true; + +//////////////////////////////////////////////////////////////////////// +// Global state +//////////////////////////////////////////////////////////////////////// +static bool +model_filter = true; //////////////////////////////////////////////////////////////////////// // Static utility functions. //////////////////////////////////////////////////////////////////////// +static int +model_filter_callback (ssgEntity * entity, int mask) +{ + return model_filter ? 1 : 0; +} + /** * Callback to update an animation. */ static int animation_callback (ssgEntity * entity, int mask) { - ((SGAnimation *)entity->getUserData())->update(); - return true; + return ((SGAnimation *)entity->getUserData())->update(); +} + +/** + * Callback to restore the state after an animation. + */ +static int +restore_callback (ssgEntity * entity, int mask) +{ + ((SGAnimation *)entity->getUserData())->restore(); + return 1; } @@ -100,8 +121,11 @@ sgMakeAnimation( ssgBranch * model, vector &name_nodes, SGPropertyNode *prop_root, SGPropertyNode_ptr node, - double sim_time_sec ) + double sim_time_sec, + SGPath &texture_path, + set &ignore_branches ) { + bool ignore = false; SGAnimation * animation = 0; const char * type = node->getStringValue("type", "none"); if (!strcmp("none", type)) { @@ -130,8 +154,19 @@ sgMakeAnimation( ssgBranch * model, animation = new SGTexMultipleAnimation(prop_root, node); } else if (!strcmp("blend", type)) { animation = new SGBlendAnimation(prop_root, node); + ignore = true; } else if (!strcmp("alpha-test", type)) { - animation = new SGAlphaTestAnimation(prop_root, node); + animation = new SGAlphaTestAnimation(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)) { + animation = new SGDistScaleAnimation(node); + } else if (!strcmp("noshadow", type)) { + animation = new SGShadowAnimation(prop_root, node); + } else if (!strcmp("shader", type)) { + animation = new SGShaderAnimation(prop_root, node); } else { animation = new SGNullAnimation(node); SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); @@ -144,7 +179,7 @@ sgMakeAnimation( ssgBranch * model, if (name_nodes.size() > 0) { object = find_named_node(model, name_nodes[0]->getStringValue()); if (object == 0) { - SG_LOG(SG_INPUT, SG_WARN, "Object " << name_nodes[0]->getStringValue() + SG_LOG(SG_INPUT, SG_ALERT, "Object " << name_nodes[0]->getStringValue() << " not found"); delete animation; animation = 0; @@ -163,21 +198,48 @@ sgMakeAnimation( ssgBranch * model, const char * name = name_nodes[i]->getStringValue(); object = find_named_node(model, name); if (object == 0) { - SG_LOG(SG_INPUT, SG_WARN, "Object " << name << " not found"); + SG_LOG(SG_INPUT, SG_ALERT, "Object " << name << " not found"); delete animation; animation = 0; + } else { + ssgBranch * oldParent = object->getParent(0); + branch->addKid(object); + oldParent->removeKid(object); } - ssgBranch * oldParent = object->getParent(0); - branch->addKid(object); - oldParent->removeKid(object); } - animation->init(); - branch->setUserData(animation); - branch->setTravCallback(SSG_CALLBACK_PRETRAV, animation_callback); + if ( animation != 0 ) { + animation->init(); + branch->setUserData(animation); + branch->setTravCallback(SSG_CALLBACK_PRETRAV, animation_callback); + branch->setTravCallback(SSG_CALLBACK_POSTTRAV, restore_callback); + if ( ignore ) { + ignore_branches.insert( branch ); + } + } +} + + +static void makeDList( ssgBranch *b, const set &ignore ) +{ + int nb = b->getNumKids(); + for (int i = 0; igetKid(i); + if (e->isAKindOf(ssgTypeLeaf())) { + if( ((ssgLeaf*)e)->getNumVertices() > 0) + ((ssgLeaf*)e)->makeDList(); + } else if (e->isAKindOf(ssgTypeBranch()) && ignore.find((ssgBranch *)e) == ignore.end()) { + makeDList( (ssgBranch*)e, ignore ); + } + } } +class sgLoaderOptions : public ssgLoaderOptions { +public: + void endLoad() {} // Avoid clearing the texture cache after every model load +}; +static sgLoaderOptions loaderOptions; //////////////////////////////////////////////////////////////////////// @@ -187,17 +249,18 @@ sgMakeAnimation( ssgBranch * model, ssgBranch * sgLoad3DModel( const string &fg_root, const string &path, SGPropertyNode *prop_root, - double sim_time_sec ) + double sim_time_sec, ssgEntity *(*load_panel)(SGPropertyNode *), + SGModelData *data ) { ssgBranch * model = 0; SGPropertyNode props; // Load the 3D aircraft object itself - SGPath modelpath = path; + SGPath modelpath = path, texturepath = path; if ( !ulIsAbsolutePathName( path.c_str() ) ) { SGPath tmp = fg_root; tmp.append(modelpath.str()); - modelpath = tmp; + modelpath = texturepath = tmp; } // Check for an XML wrapper @@ -206,6 +269,10 @@ sgLoad3DModel( const string &fg_root, const string &path, if (props.hasValue("/path")) { modelpath = modelpath.dir(); modelpath.append(props.getStringValue("/path")); + if (props.hasValue("/texture-path")) { + texturepath = texturepath.dir(); + texturepath.append(props.getStringValue("/texture-path")); + } } else { if (model == 0) model = new ssgBranch; @@ -215,14 +282,19 @@ sgLoad3DModel( const string &fg_root, const string &path, // Assume that textures are in // the same location as the XML file. if (model == 0) { - ssgTexturePath((char *)modelpath.dir().c_str()); - model = (ssgBranch *)ssgLoad((char *)modelpath.c_str()); + if (texturepath.extension() != "") + texturepath = texturepath.dir(); + + ssgTexturePath((char *)texturepath.c_str()); + model = (ssgBranch *)ssgLoad((char *)modelpath.c_str(), &loaderOptions); if (model == 0) - throw sg_exception("Failed to load 3D model"); + throw sg_io_exception("Failed to load 3D model", + sg_location(modelpath.str())); } - // Set up the alignment node ssgTransform * alignmainmodel = new ssgTransform; + if ( load_panel == 0 ) + alignmainmodel->setTravCallback( SSG_CALLBACK_PRETRAV, model_filter_callback ); alignmainmodel->addKid(model); sgMat4 res_matrix; sgMakeOffsetsMatrix(&res_matrix, @@ -236,16 +308,6 @@ sgLoad3DModel( const string &fg_root, const string &path, unsigned int i; - // Load animations - vector animation_nodes = props.getChildren("animation"); - for (i = 0; i < animation_nodes.size(); i++) { - const char * name = animation_nodes[i]->getStringValue("name", 0); - vector name_nodes = - animation_nodes[i]->getChildren("object-name"); - sgMakeAnimation( model, name, name_nodes, prop_root, animation_nodes[i], - sim_time_sec); - } - // Load sub-models vector model_nodes = props.getChildren("model"); for (i = 0; i < model_nodes.size(); i++) { @@ -261,14 +323,72 @@ sgLoad3DModel( const string &fg_root, const string &path, node->getFloatValue("offsets/z-m", 0.0)); align->setTransform(res_matrix); - ssgBranch * kid = sgLoad3DModel( fg_root, node->getStringValue("path"), - prop_root, sim_time_sec ); + ssgBranch * kid; + const char * submodel = node->getStringValue("path"); + try { + kid = sgLoad3DModel( fg_root, submodel, prop_root, sim_time_sec, load_panel ); + + } catch (const sg_throwable &t) { + SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage()); + throw; + } align->addKid(kid); + align->setName(node->getStringValue("name", "")); model->addKid(align); } + if ( load_panel ) { + // Load panels + vector panel_nodes = props.getChildren("panel"); + for (i = 0; i < panel_nodes.size(); i++) { + SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel"); + ssgEntity * panel = load_panel(panel_nodes[i]); + if (panel_nodes[i]->hasValue("name")) + panel->setName((char *)panel_nodes[i]->getStringValue("name")); + model->addKid(panel); + } + } + + if (data) { + alignmainmodel->setUserData(data); + data->modelLoaded(path, &props, alignmainmodel); + } + // Load animations + set ignore_branches; + vector animation_nodes = props.getChildren("animation"); + for (i = 0; i < animation_nodes.size(); i++) { + const char * name = animation_nodes[i]->getStringValue("name", 0); + vector name_nodes = + animation_nodes[i]->getChildren("object-name"); + sgMakeAnimation( model, name, name_nodes, prop_root, animation_nodes[i], + sim_time_sec, texturepath, ignore_branches); + } + +#if PLIB_VERSION > 183 + if ( model != 0 && sgUseDisplayList ) { + makeDList( model, ignore_branches ); + } +#endif + + int m = props.getIntValue("dump", 0); + if (m > 0) + model->print(stderr, "", m - 1); + return alignmainmodel; } +bool +sgSetModelFilter( bool filter ) +{ + bool old = model_filter; + model_filter = filter; + return old; +} + +bool +sgCheckAnimationBranch (ssgEntity * entity) +{ + return entity->getTravCallback(SSG_CALLBACK_PRETRAV) == animation_callback; +} // end of model.cxx