|
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;
}
|