From: <mk...@us...> - 2003-07-18 21:05:17
|
Update of /cvsroot/csp/APPLICATIONS/CSPSim/Source In directory sc8-pr-cvs1:/tmp/cvs-serv26067/Source Modified Files: ObjectModel.cpp Log Message: Index: ObjectModel.cpp =================================================================== RCS file: /cvsroot/csp/APPLICATIONS/CSPSim/Source/ObjectModel.cpp,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** ObjectModel.cpp 2 Jul 2003 20:01:58 -0000 1.16 --- ObjectModel.cpp 18 Jul 2003 21:05:14 -0000 1.17 *************** *** 28,31 **** --- 28,32 ---- #include "ObjectModel.h" + #include "Animation.h" #include "Log.h" #include "Config.h" *************** *** 41,44 **** --- 42,47 ---- #include <osg/Texture> #include <osg/Geode> + #include <osg/Depth> + #include <osgText/Text> #include <osg/PolygonOffset> #include <osg/CullFace> *************** *** 47,54 **** --- 50,121 ---- #include <SimData/osg.h> + /* + TODO + + o adjust contact markers and view point for model + transform + + o implement ModelProcessor + + */ SIMDATA_REGISTER_INTERFACE(ObjectModel) + /** + * Animation binding helper that can be attached to model + * nodes (using osg::Object user data). When the model + * prototype is cloned, these bindings help to connect the + * new animation transform nodes to the correct animation + * callback. + */ + class AnimationBinding: public osg::Referenced { + simdata::Ref<Animation const> m_Animation; + public: + AnimationBinding(Animation const* animation): m_Animation(animation) {} + inline AnimationCallback *bind(osg::Node *node) const { + return m_Animation->newCallback(node); + } + }; + + + /** + * A visitor for model prototypes to attach animation + * bindings to the appropriate nodes. Each prototype + * only needs to be processed once, immediately after + * loading the model. The bindings are used when the + * model is later cloned by SceneModel to attach + * animation callbacks. + */ + class ModelProcessor: public osg::NodeVisitor { + osg::ref_ptr<osg::Node> m_Root; + simdata::Link<Animation>::vector const *m_Animations; + public: + ModelProcessor(): NodeVisitor(TRAVERSE_ALL_CHILDREN), m_Animations(0) { } + void setAnimations(simdata::Link<Animation>::vector const *animations) { + m_Animations = animations; + } + virtual void apply(osg::Transform &node) { + if (!m_Animations) return; + std::string name = node.getName(); + std::cout << "MODEL TRANSFORM: " << name << "\n"; + if (name.substr(0,6) == "ANIM: ") { + simdata::Key id = name.substr(6); + simdata::Link<Animation>::vector::const_iterator i = m_Animations->begin(); + std::cout << "SEARCHING FOR " << name.substr(6) << " (" << id << ")\n"; + for (; i != m_Animations->end(); ++i) { + std::cout << "COMPARING TO " << (*i)->getModelID() << "\n"; + if ((*i)->getModelID() == id) { + node.setUserData(new AnimationBinding(i->get())); + std::cout << "FOUND\n"; + break; + } + } + } + } + }; + + + /** * Visit nodes, applying anisotropic filtering to textures. *************** *** 133,136 **** --- 200,204 ---- p.pack(m_CullFace); p.pack(m_LandingGear); + p.pack(m_Animations); } *************** *** 150,153 **** --- 218,222 ---- p.unpack(m_CullFace); p.unpack(m_LandingGear); + p.unpack(m_Animations); } *************** *** 202,212 **** void ObjectModel::loadModel() { - /* - if (g_ModelPath == "") { - g_ModelPath = getDataPath("ModelPath"); - } - - std::string source = simdata::ospath::filter(simdata::ospath::join(g_ModelPath, m_ModelPath.getSource())); - */ std::string source = m_ModelPath.getSource(); --- 271,274 ---- *************** *** 223,231 **** assert(pNode); ! m_Node = pNode; ! m_Node->setName(m_ModelPath.getSource()); if (m_PolygonOffset != 0.0) { ! osg::StateSet *ss = m_Node->getOrCreateStateSet(); osg::PolygonOffset *po = new osg::PolygonOffset; po->setFactor(-1.0); --- 285,293 ---- assert(pNode); ! m_Model = pNode; ! m_Model->setName(m_ModelPath.getSource()); if (m_PolygonOffset != 0.0) { ! osg::StateSet *ss = m_Model->getOrCreateStateSet(); osg::PolygonOffset *po = new osg::PolygonOffset; po->setFactor(-1.0); *************** *** 236,240 **** if (m_CullFace != 0) { // XXX should reuse a single static CullFace instance. ! osg::StateSet *ss = m_Node->getOrCreateStateSet(); osg::CullFace *cf = new osg::CullFace; cf->setMode(m_CullFace < 0 ? osg::CullFace::BACK : osg::CullFace::FRONT); --- 298,302 ---- if (m_CullFace != 0) { // XXX should reuse a single static CullFace instance. ! osg::StateSet *ss = m_Model->getOrCreateStateSet(); osg::CullFace *cf = new osg::CullFace; cf->setMode(m_CullFace < 0 ? osg::CullFace::BACK : osg::CullFace::FRONT); *************** *** 242,252 **** } ! // XXX should do this after scaling, no? ! osg::BoundingSphere s = m_Node->getBound(); ! m_BoundingSphereRadius = s.radius(); ! ! m_Transform = new osg::MatrixTransform; ! m_Transform->setName("MODEL TRANSFORM"); ! m_Transform->addChild(m_Node.get()); assert(m_Axis0.Length() > 0.0); --- 304,329 ---- } ! if (m_Smooth) { ! osgUtil::SmoothingVisitor sv; ! m_Model->accept(sv); ! } ! ! if (m_Filter) { ! // FIXME: level should come from global graphics settings ! TrilinearFilterVisitor tfv(16.0); ! m_Model->accept(tfv); ! } ! ! osgUtil::Optimizer opt; ! opt.optimize(m_Model.get()); ! ! // add animation hooks to user data field of animation ! // transform nodes ! ModelProcessor processor; ! std::cout << "ANIMATIONS AVAILABLE: " << m_Animations.size() << "\n"; ! processor.setAnimations(&m_Animations); ! std::cout << "PROCESSING MODEL\n"; ! m_Model->accept(processor); ! std::cout << "PROCESSING MODEL DONE\n"; assert(m_Axis0.Length() > 0.0); *************** *** 256,295 **** assert(m_Axis1.Length() > 0.0); m_Axis1.Normalize(); - // find third axis - simdata::Vector3 axis2 = simdata::Cross(m_Axis0, m_Axis1); - - simdata::Matrix3 o(m_Axis0.x, m_Axis0.y, m_Axis0.z, m_Axis1.x, m_Axis1.y, m_Axis1.z, axis2.x, axis2.y, axis2.z); - o = o.Inverse() * m_Scale; - simdata::Matrix3::M_t (&R)[3][3] = o.rowcol; - osg::Matrix model_orientation; - model_orientation.set( - R[0][0], R[1][0], R[2][0], 0.0, - R[0][1], R[1][1], R[2][1], 0.0, - R[0][2], R[1][2], R[2][2], 0.0, - m_Offset.x, m_Offset.y, m_Offset.z, 1.0 - ); - m_Transform->setMatrix(model_orientation); ! if (m_Scale != 1.0) { ! m_Transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); } //osg::StateSet * stateSet = m_rpNode->getStateSet(); //stateSet->setGlobalDefaults(); //m_rpNode->setStateSet(stateSet); - if (m_Smooth) { - osgUtil::SmoothingVisitor sv; - m_Transform->accept(sv); - } - - if (m_Filter) { - // FIXME: level should come from global graphics settings - TrilinearFilterVisitor tfv(16.0); - m_Transform->accept(tfv); - } - m_DebugMarkers = new osg::Switch; ! m_Transform->addChild(m_DebugMarkers.get()); // create visible markers for each contact point --- 333,384 ---- assert(m_Axis1.Length() > 0.0); m_Axis1.Normalize(); ! // insert an adjustment matrix at the head of the model only ! // if necessary. ! if (m_Axis0 != simdata::Vector3::XAXIS || ! m_Axis1 != simdata::Vector3::YAXIS || ! m_Scale != 1.0 || ! m_Offset != simdata::Vector3::ZERO) { ! // find third axis and make the transform matrix ! simdata::Vector3 axis2 = simdata::Cross(m_Axis0, m_Axis1); ! simdata::Matrix3 o(m_Axis0.x, m_Axis0.y, m_Axis0.z, ! m_Axis1.x, m_Axis1.y, m_Axis1.z, ! axis2.x, axis2.y, axis2.z); ! o = o.Inverse() * m_Scale; ! simdata::Matrix3::M_t (&R)[3][3] = o.rowcol; ! osg::Matrix model_orientation; ! model_orientation.set( ! R[0][0], R[1][0], R[2][0], 0.0, ! R[0][1], R[1][1], R[2][1], 0.0, ! R[0][2], R[1][2], R[2][2], 0.0, ! m_Offset.x, m_Offset.y, m_Offset.z, 1.0 ! ); ! osg::MatrixTransform *adjust = new osg::MatrixTransform; ! if (m_Scale != 1.0) { ! adjust->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); ! } ! adjust->setName("XML_ADJUSTMENT"); ! adjust->setDataVariance(osg::Object::STATIC); ! adjust->setMatrix(model_orientation); ! adjust->addChild(m_Model.get()); ! m_Model = adjust; ! simdata::Matrix3 sd_adjust = simdata::fromOSG(model_orientation).Inverse(); ! for (unsigned i = 0; i < m_Contacts.size(); i++) { ! m_Contacts[i] = sd_adjust * m_Contacts[i] + m_Offset; ! } ! m_ViewPoint = sd_adjust * m_ViewPoint + m_Offset; } + osg::BoundingSphere s = m_Model->getBound(); + m_BoundingSphereRadius = s.radius(); + //osg::StateSet * stateSet = m_rpNode->getStateSet(); //stateSet->setGlobalDefaults(); //m_rpNode->setStateSet(stateSet); m_DebugMarkers = new osg::Switch; ! // XXX should reuse a single static stateset? ! m_DebugMarkers->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); ! m_DebugMarkers->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace, osg::StateAttribute::ON); // create visible markers for each contact point *************** *** 299,311 **** addGearSprites(); - // TODO: run an optimizer to flatten the model transform (if it differs from identity) - osgUtil::Optimizer opt; - opt.optimize(m_Transform.get()); - osg::ref_ptr<osg::State> state = new osg::State; osgUtil::DisplayListVisitor dlv(osgUtil::DisplayListVisitor::COMPILE_DISPLAY_LISTS); dlv.setState(state.get()); dlv.setNodeMaskOverride(0xffffffff); ! m_Transform->accept(dlv); } --- 388,397 ---- addGearSprites(); osg::ref_ptr<osg::State> state = new osg::State; osgUtil::DisplayListVisitor dlv(osgUtil::DisplayListVisitor::COMPILE_DISPLAY_LISTS); dlv.setState(state.get()); dlv.setNodeMaskOverride(0xffffffff); ! m_Model->accept(dlv); ! m_DebugMarkers->accept(dlv); } *************** *** 457,461 **** makeLeftGear(m_LandingGear[1]); makeRightGear(m_LandingGear[2]); ! m_Transform->addChild(m_GearSprites.get()); } } --- 543,547 ---- makeLeftGear(m_LandingGear[1]); makeRightGear(m_LandingGear[2]); ! m_DebugMarkers->addChild(m_GearSprites.get()); } } *************** *** 499,508 **** --- 585,672 ---- + + /** + * Copy class for cloning model prototypes for use + * in the scene graph. Each new SceneModel uses this + * class to create a copy of the associated ObjectModel + * prototype. + */ + class ModelCopy: public osg::CopyOp { + public: + typedef std::vector<osg::ref_ptr<AnimationCallback> > AnimationCallbackVector; + inline AnimationCallbackVector const &getAnimationCallbacks() const { + return m_AnimationCallbacks; + } + virtual osg::Node* operator() (const osg::Node* node) const { + osg::Referenced const *data = node->getUserData(); + // user data bound to nodes is used to modify the copy operations + if (data) { + AnimationBinding const *binding = dynamic_cast<AnimationBinding const *>(data); + // nodes with animation bindings need a callback + if (binding) { + osg::Node *new_node = dynamic_cast<osg::Node*>(node->clone(*this)); + m_AnimationCallbacks.push_back(binding->bind(new_node)); + std::cout << "ADDED CALLBACK\n"; + return new_node; + } + } + if (dynamic_cast<osg::Group const *>(node)) { + // clone groups + return dynamic_cast<osg::Node*>(node->clone(*this)); + } else { + // copy other leaf nodes by reference + return const_cast<osg::Node*>(node); + } + } + private: + mutable AnimationCallbackVector m_AnimationCallbacks; + }; + SceneModel::SceneModel(simdata::Ref<ObjectModel> const & model) { m_Model = model; assert(m_Model.valid()); CSP_LOG(APP, INFO, "create SceneModel for " << m_Model->getModelPath()); + + // get the prototype model scene graph osg::Node *model_node = m_Model->getModel().get(); assert(model_node); + + // create a working copy + ModelCopy model_copy; + model_node = model_copy(model_node); + + std::cout << "MODEL COPIED\n"; + + std::cout << "MODEL animation count = " << model_copy.getAnimationCallbacks().size() << "\n"; + + m_AnimationCallbacks.resize(model_copy.getAnimationCallbacks().size()); + + // store all the animation update callbacks + std::copy(model_copy.getAnimationCallbacks().begin(), + model_copy.getAnimationCallbacks().end(), + m_AnimationCallbacks.begin()); + + std::cout << "MODEL animation count = " << m_AnimationCallbacks.size() << "\n"; + + m_Label = new osgText::Text(); + m_Label->setFont("screeninfo.ttf"); + m_Label->setFontSize(16, 16); + m_Label->setColor(osg::Vec4(0.3f, 0.4f, 1.0f, 1.0f)); + m_Label->setCharacterSize(100.0, 1.0); + m_Label->setPosition(osg::Vec3(6, 0, 0)); + m_Label->setText("AIRCRAFT"); + osg::Geode *label = new osg::Geode; + osg::Depth *depth = new osg::Depth; + depth->setFunction(osg::Depth::ALWAYS); + depth->setRange(1.0, 1.0); + label->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::OFF); + label->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + //setMatrix(osg::Matrix::ortho2D(0,ScreenWidth,0,ScreenHeight)); + osg::MatrixTransform *m_modelview_abs = new osg::MatrixTransform; + m_modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE); + m_modelview_abs->setMatrix(osg::Matrix::identity()); + m_modelview_abs->addChild(label); + + // XXX the switch node is probably not necessary in most cases and should be removed // to switch between various representations of the same object (depending on views for example) m_Switch = new osg::Switch; *************** *** 511,514 **** --- 675,680 ---- m_Transform = new osg::PositionAttitudeTransform; m_Transform->addChild(m_Switch.get()); + m_Transform->addChild(m_Model->getDebugMarkers().get()); + m_Transform->addChild(m_modelview_abs); m_Smoke = false; //show(); *************** *** 522,525 **** --- 688,695 ---- } + void SceneModel::setLabel(std::string const &label) { + m_Label->setText(label); + } + void SceneModel::updateSmoke(double dt, simdata::Vector3 const &global_position, simdata::Quaternion const &attitude) { m_SmokeTrails->update(dt, global_position, attitude); *************** *** 579,649 **** } } - // FIXME: from SimObject.... needs to be incorparated: - /* - void SimObject::initModel() - { - CSP_LOG(APP, DEBUG, "SimObject::initModel() - ID: " << m_iObjectID); - - assert(m_rpNode == NULL && m_rpSwitch == NULL && m_rpTransform == NULL); - assert(m_Model.valid()); - - std::cout << "INIT MODEL\n"; - - m_rpNode = m_Model->getModel(); - - //osg::StateSet * stateSet = m_rpNode->getStateSet(); - //stateSet->setGlobalDefaults(); - //m_rpNode->setStateSet(stateSet); - - // to switch between various representants of same object (depending on views for example) - m_rpSwitch = new osg::Switch; - m_rpSwitch->setName("MODEL SWITCH"); - m_rpSwitch->addChild(m_rpNode.get()); - - // master object to which all others ones are linked - m_rpTransform = new osg::MatrixTransform; - m_rpTransform->setName("MODEL TRANSFORM"); - - m_rpTransform->addChild( m_rpSwitch.get() ); - //m_rpSwitch->setAllChildrenOn(); - } ! if (m_rpTransform != NULL && m_rpSwitch != NULL) { ! m_rpTransform->removeChild( m_rpSwitch.get() ); } ! ! void SimObject::ShowRepresentant(unsigned short const p_usflag) ! { ! m_rpSwitch->setAllChildrenOff(); ! m_rpSwitch->setValue(p_usflag, true); } - osg::Matrix worldMat; - simdata::Matrix3::M_t (&R)[3][3] = m_Orientation.rowcol; - worldMat.set(R[0][0], R[1][0], R[2][0], 0.0, - R[0][1], R[1][1], R[2][1], 0.0, - R[0][2], R[1][2], R[2][2], 0.0, - m_LocalPosition.x, m_LocalPosition.y, m_LocalPosition.z, 1.0); - //m_rpTransform->setReferenceFrame(osg::Transform::RELATIVE_TO_PARENTS); - - m_rpTransform->setMatrix(worldMat); - - // FIXME: call specific versions of this from derived classes: - //scene->addNodeToScene(m_rpTransform.get()); - - setCullingActive(true); - - //CSP_LOG(APP, DEBUG, "NodeName: " << m_rpNode->getName() << - // ", BoundingPos: " << sphere.center() << ", BoundingRadius: " << - // sphere.radius() ); - - - void SimObject::setCullingActive(bool flag) - { - if (m_rpTransform.valid()) { - m_rpTransform->setCullingActive(flag); - } - } - - */ --- 749,763 ---- } } ! AnimationChannel *SceneModel::bindAnimationChannel(std::string const &control, AnimationChannel *channel) { ! simdata::Key id(control); ! int index, n = m_AnimationCallbacks.size(); ! for (index = 0; index < n; ++index) { ! if (m_AnimationCallbacks[index]->getControlID() == id) { ! m_AnimationCallbacks[index]->bindChannel(channel); ! } } ! return channel; } |