mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-15 09:39:53 +00:00
Refactor controllers, now part of the scene graph as UpdateCallbacks
Practical benefits: - The controller update is now run automatically - Creating an instance of a scene graph should now work properly using the defined copy constructors
This commit is contained in:
parent
af27a10b0c
commit
4957ceeb1d
@ -112,15 +112,11 @@ int main(int argc, char** argv)
|
||||
|
||||
//osgDB::writeNodeFile(*newNode, "out.osg");
|
||||
|
||||
std::vector<NifOsg::Controller > controllers;
|
||||
osg::Group* newNode = new osg::Group;
|
||||
NifOsg::Loader loader;
|
||||
loader.resourceManager = &resourceMgr;
|
||||
loader.loadAsSkeleton(nif, newNode);
|
||||
|
||||
for (unsigned int i=0; i<loader.mControllers.size(); ++i)
|
||||
controllers.push_back(loader.mControllers[i]);
|
||||
|
||||
osg::PositionAttitudeTransform* trans = new osg::PositionAttitudeTransform;
|
||||
root->addChild(trans);
|
||||
|
||||
@ -137,6 +133,8 @@ int main(int argc, char** argv)
|
||||
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
|
||||
viewer.addEventHandler(new WireframeKeyHandler(root));
|
||||
|
||||
//viewer.getCamera()->setCullMask()
|
||||
|
||||
// We're going to change this from the event callback, set the variance to DYNAMIC so that
|
||||
// we don't interfere with the draw thread.
|
||||
root->getOrCreateStateSet()->setDataVariance(osg::Node::DYNAMIC);
|
||||
@ -148,9 +146,6 @@ int main(int argc, char** argv)
|
||||
//trans->setAttitude(osg::Quat(viewer.getFrameStamp()->getSimulationTime()*5, osg::Vec3f(0,0,1)));
|
||||
|
||||
viewer.frame();
|
||||
|
||||
for (unsigned int i=0; i<controllers.size(); ++i)
|
||||
controllers[i].update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -30,7 +30,7 @@ void CSVRender::UnpagedWorldspaceWidget::update()
|
||||
|
||||
/// \todo deal with mSunlight and mFog/mForDensity
|
||||
|
||||
//flagAsModified();
|
||||
flagAsModified();
|
||||
}
|
||||
|
||||
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
|
||||
|
@ -48,7 +48,53 @@ float ControllerFunction::calculate(float value)
|
||||
return value;
|
||||
}
|
||||
|
||||
osg::Quat KeyframeControllerValue::interpKey(const Nif::QuaternionKeyMap::MapType &keys, float time)
|
||||
FrameTimeSource::FrameTimeSource()
|
||||
: mLastTime(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
float FrameTimeSource::getValue(osg::NodeVisitor *nv)
|
||||
{
|
||||
// TODO: dt could be computed globally instead of once per instance
|
||||
double time = nv->getFrameStamp()->getReferenceTime();
|
||||
float dt = static_cast<float>(time - mLastTime);
|
||||
mLastTime = time;
|
||||
return dt;
|
||||
}
|
||||
|
||||
KeyframeController::KeyframeController()
|
||||
{
|
||||
}
|
||||
|
||||
KeyframeController::KeyframeController(const KeyframeController ©, const osg::CopyOp ©op)
|
||||
: osg::NodeCallback(copy, copyop)
|
||||
, Controller(copy)
|
||||
, mRotations(copy.mRotations)
|
||||
, mXRotations(copy.mXRotations)
|
||||
, mYRotations(copy.mYRotations)
|
||||
, mZRotations(copy.mZRotations)
|
||||
, mTranslations(copy.mTranslations)
|
||||
, mScales(copy.mScales)
|
||||
, mNif(copy.mNif)
|
||||
, mInitialQuat(copy.mInitialQuat)
|
||||
, mInitialScale(copy.mInitialScale)
|
||||
{
|
||||
}
|
||||
|
||||
KeyframeController::KeyframeController(const Nif::NIFFilePtr &nif, const Nif::NiKeyframeData *data,
|
||||
osg::Quat initialQuat, float initialScale)
|
||||
: mRotations(&data->mRotations)
|
||||
, mXRotations(&data->mXRotations)
|
||||
, mYRotations(&data->mYRotations)
|
||||
, mZRotations(&data->mZRotations)
|
||||
, mTranslations(&data->mTranslations)
|
||||
, mScales(&data->mScales)
|
||||
, mNif(nif)
|
||||
, mInitialQuat(initialQuat)
|
||||
, mInitialScale(initialScale)
|
||||
{ }
|
||||
|
||||
osg::Quat KeyframeController::interpKey(const Nif::QuaternionKeyMap::MapType &keys, float time)
|
||||
{
|
||||
if(time <= keys.begin()->first)
|
||||
return keys.begin()->second.mValue;
|
||||
@ -81,7 +127,7 @@ osg::Quat KeyframeControllerValue::interpKey(const Nif::QuaternionKeyMap::MapTyp
|
||||
return keys.rbegin()->second.mValue;
|
||||
}
|
||||
|
||||
osg::Quat KeyframeControllerValue::getXYZRotation(float time) const
|
||||
osg::Quat KeyframeController::getXYZRotation(float time) const
|
||||
{
|
||||
float xrot = interpKey(mXRotations->mKeys, time);
|
||||
float yrot = interpKey(mYRotations->mKeys, time);
|
||||
@ -92,96 +138,108 @@ osg::Quat KeyframeControllerValue::getXYZRotation(float time) const
|
||||
return (zr*yr*xr);
|
||||
}
|
||||
|
||||
KeyframeControllerValue::KeyframeControllerValue(osg::Node *target, const Nif::NIFFilePtr &nif, const Nif::NiKeyframeData *data,
|
||||
osg::Quat initialQuat, float initialScale)
|
||||
: NodeTargetValue(target)
|
||||
, mRotations(&data->mRotations)
|
||||
, mXRotations(&data->mXRotations)
|
||||
, mYRotations(&data->mYRotations)
|
||||
, mZRotations(&data->mZRotations)
|
||||
, mTranslations(&data->mTranslations)
|
||||
, mScales(&data->mScales)
|
||||
, mNif(nif)
|
||||
, mInitialQuat(initialQuat)
|
||||
, mInitialScale(initialScale)
|
||||
{ }
|
||||
|
||||
osg::Vec3f KeyframeControllerValue::getTranslation(float time) const
|
||||
osg::Vec3f KeyframeController::getTranslation(float time) const
|
||||
{
|
||||
if(mTranslations->mKeys.size() > 0)
|
||||
return interpKey(mTranslations->mKeys, time);
|
||||
osg::MatrixTransform* trans = static_cast<osg::MatrixTransform*>(mNode);
|
||||
return trans->getMatrix().getTrans();
|
||||
return osg::Vec3f();
|
||||
}
|
||||
|
||||
void KeyframeControllerValue::setValue(float time)
|
||||
void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
osg::MatrixTransform* trans = static_cast<osg::MatrixTransform*>(mNode);
|
||||
osg::Matrix mat = trans->getMatrix();
|
||||
|
||||
if(mRotations->mKeys.size() > 0)
|
||||
mat.setRotate(interpKey(mRotations->mKeys, time));
|
||||
else if (!mXRotations->mKeys.empty() || !mYRotations->mKeys.empty() || !mZRotations->mKeys.empty())
|
||||
mat.setRotate(getXYZRotation(time));
|
||||
else
|
||||
mat.setRotate(mInitialQuat);
|
||||
|
||||
// let's hope no one's using multiple KeyframeControllers on the same node (not that would make any sense...)
|
||||
float scale = mInitialScale;
|
||||
if(mScales->mKeys.size() > 0)
|
||||
scale = interpKey(mScales->mKeys, time);
|
||||
|
||||
for (int i=0;i<3;++i)
|
||||
for (int j=0;j<3;++j)
|
||||
mat(i,j) *= scale;
|
||||
|
||||
if(mTranslations->mKeys.size() > 0)
|
||||
mat.setTrans(interpKey(mTranslations->mKeys, time));
|
||||
trans->setMatrix(mat);
|
||||
}
|
||||
|
||||
Controller::Controller(boost::shared_ptr<ControllerSource> src, boost::shared_ptr<ControllerValue> dest, boost::shared_ptr<ControllerFunction> function)
|
||||
: mSource(src)
|
||||
, mDestValue(dest)
|
||||
, mFunction(function)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Controller::update()
|
||||
{
|
||||
if (mSource.get())
|
||||
if (hasInput())
|
||||
{
|
||||
mDestValue->setValue(mFunction->calculate(mSource->getValue()));
|
||||
osg::MatrixTransform* trans = static_cast<osg::MatrixTransform*>(node);
|
||||
osg::Matrix mat = trans->getMatrix();
|
||||
|
||||
float time = getInputValue(nv);
|
||||
|
||||
if(mRotations->mKeys.size() > 0)
|
||||
mat.setRotate(interpKey(mRotations->mKeys, time));
|
||||
else if (!mXRotations->mKeys.empty() || !mYRotations->mKeys.empty() || !mZRotations->mKeys.empty())
|
||||
mat.setRotate(getXYZRotation(time));
|
||||
else
|
||||
mat.setRotate(mInitialQuat);
|
||||
|
||||
// let's hope no one's using multiple KeyframeControllers on the same node (not that would make any sense...)
|
||||
float scale = mInitialScale;
|
||||
if(mScales->mKeys.size() > 0)
|
||||
scale = interpKey(mScales->mKeys, time);
|
||||
|
||||
for (int i=0;i<3;++i)
|
||||
for (int j=0;j<3;++j)
|
||||
mat(i,j) *= scale;
|
||||
|
||||
if(mTranslations->mKeys.size() > 0)
|
||||
mat.setTrans(interpKey(mTranslations->mKeys, time));
|
||||
trans->setMatrix(mat);
|
||||
}
|
||||
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
Controller::Controller()
|
||||
{
|
||||
}
|
||||
|
||||
bool Controller::hasInput() const
|
||||
{
|
||||
return mSource.get() != NULL;
|
||||
}
|
||||
|
||||
float Controller::getInputValue(osg::NodeVisitor* nv)
|
||||
{
|
||||
return mFunction->calculate(mSource->getValue(nv));
|
||||
}
|
||||
|
||||
GeomMorpherController::GeomMorpherController()
|
||||
{
|
||||
}
|
||||
|
||||
GeomMorpherController::GeomMorpherController(const GeomMorpherController ©, const osg::CopyOp ©op)
|
||||
: osg::Drawable::UpdateCallback(copy, copyop)
|
||||
, Controller(copy)
|
||||
, mMorphs(copy.mMorphs)
|
||||
{
|
||||
}
|
||||
|
||||
GeomMorpherController::GeomMorpherController(const Nif::NiMorphData *data)
|
||||
: mMorphs(data->mMorphs)
|
||||
{
|
||||
}
|
||||
|
||||
void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable)
|
||||
{
|
||||
osgAnimation::MorphGeometry* morphGeom = dynamic_cast<osgAnimation::MorphGeometry*>(drawable);
|
||||
if (morphGeom)
|
||||
{
|
||||
if (hasInput())
|
||||
{
|
||||
if (mMorphs.size() <= 1)
|
||||
return;
|
||||
float input = getInputValue(nv);
|
||||
int i = 0;
|
||||
for (std::vector<Nif::NiMorphData::MorphData>::iterator it = mMorphs.begin()+1; it != mMorphs.end(); ++it,++i)
|
||||
{
|
||||
float val = 0;
|
||||
if (!it->mData.mKeys.empty())
|
||||
val = interpKey(it->mData.mKeys, input);
|
||||
val = std::max(0.f, std::min(1.f, val));
|
||||
|
||||
morphGeom->setWeight(i, val);
|
||||
}
|
||||
}
|
||||
|
||||
morphGeom->transformSoftwareMethod();
|
||||
}
|
||||
}
|
||||
|
||||
GeomMorpherControllerValue::GeomMorpherControllerValue(osgAnimation::MorphGeometry *geom, const Nif::NiMorphData* morphData)
|
||||
: mGeom(geom)
|
||||
, mMorphs(morphData->mMorphs)
|
||||
UVController::UVController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GeomMorpherControllerValue::setValue(float time)
|
||||
{
|
||||
if (mMorphs.size() <= 1)
|
||||
return;
|
||||
int i = 0;
|
||||
for (std::vector<Nif::NiMorphData::MorphData>::iterator it = mMorphs.begin()+1; it != mMorphs.end(); ++it,++i)
|
||||
{
|
||||
float val = 0;
|
||||
if (!it->mData.mKeys.empty())
|
||||
val = interpKey(it->mData.mKeys, time);
|
||||
val = std::max(0.f, std::min(1.f, val));
|
||||
|
||||
mGeom->setWeight(i, val);
|
||||
}
|
||||
}
|
||||
|
||||
UVControllerValue::UVControllerValue(osg::StateSet *target, const Nif::NiUVData *data, std::set<int> textureUnits)
|
||||
: mStateSet(target)
|
||||
, mUTrans(data->mKeyList[0])
|
||||
UVController::UVController(const Nif::NiUVData *data, std::set<int> textureUnits)
|
||||
: mUTrans(data->mKeyList[0])
|
||||
, mVTrans(data->mKeyList[1])
|
||||
, mUScale(data->mKeyList[2])
|
||||
, mVScale(data->mKeyList[3])
|
||||
@ -189,26 +247,58 @@ UVControllerValue::UVControllerValue(osg::StateSet *target, const Nif::NiUVData
|
||||
{
|
||||
}
|
||||
|
||||
void UVControllerValue::setValue(float value)
|
||||
UVController::UVController(const UVController& copy, const osg::CopyOp& copyop)
|
||||
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop), Controller(copy)
|
||||
, mUTrans(copy.mUTrans)
|
||||
, mVTrans(copy.mVTrans)
|
||||
, mUScale(copy.mUScale)
|
||||
, mVScale(copy.mVScale)
|
||||
, mTextureUnits(copy.mTextureUnits)
|
||||
{
|
||||
float uTrans = interpKey(mUTrans.mKeys, value, 0.0f);
|
||||
float vTrans = interpKey(mVTrans.mKeys, value, 0.0f);
|
||||
float uScale = interpKey(mUScale.mKeys, value, 1.0f);
|
||||
float vScale = interpKey(mVScale.mKeys, value, 1.0f);
|
||||
|
||||
osg::Matrixf mat = osg::Matrixf::scale(uScale, vScale, 1);
|
||||
mat.setTrans(uTrans, vTrans, 0);
|
||||
|
||||
osg::TexMat* texMat = new osg::TexMat;
|
||||
texMat->setMatrix(mat);
|
||||
|
||||
for (std::set<int>::const_iterator it = mTextureUnits.begin(); it != mTextureUnits.end(); ++it)
|
||||
{
|
||||
mStateSet->setTextureAttributeAndModes(*it, texMat, osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
|
||||
bool VisControllerValue::calculate(float time) const
|
||||
void UVController::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (hasInput())
|
||||
{
|
||||
osg::StateSet* stateset = node->getStateSet();
|
||||
float value = getInputValue(nv);
|
||||
float uTrans = interpKey(mUTrans.mKeys, value, 0.0f);
|
||||
float vTrans = interpKey(mVTrans.mKeys, value, 0.0f);
|
||||
float uScale = interpKey(mUScale.mKeys, value, 1.0f);
|
||||
float vScale = interpKey(mVScale.mKeys, value, 1.0f);
|
||||
|
||||
osg::Matrixf mat = osg::Matrixf::scale(uScale, vScale, 1);
|
||||
mat.setTrans(uTrans, vTrans, 0);
|
||||
|
||||
osg::TexMat* texMat = new osg::TexMat;
|
||||
texMat->setMatrix(mat);
|
||||
|
||||
for (std::set<int>::const_iterator it = mTextureUnits.begin(); it != mTextureUnits.end(); ++it)
|
||||
{
|
||||
stateset->setTextureAttributeAndModes(*it, texMat, osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
VisController::VisController(const Nif::NiVisData *data)
|
||||
: mData(data->mVis)
|
||||
{
|
||||
}
|
||||
|
||||
VisController::VisController()
|
||||
{
|
||||
}
|
||||
|
||||
VisController::VisController(const VisController ©, const osg::CopyOp ©op)
|
||||
: osg::NodeCallback(copy, copyop)
|
||||
, Controller(copy)
|
||||
, mData(copy.mData)
|
||||
{
|
||||
}
|
||||
|
||||
bool VisController::calculate(float time) const
|
||||
{
|
||||
if(mData.size() == 0)
|
||||
return true;
|
||||
@ -221,77 +311,140 @@ bool VisControllerValue::calculate(float time) const
|
||||
return mData.back().isSet;
|
||||
}
|
||||
|
||||
void VisControllerValue::setValue(float time)
|
||||
void VisController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
bool vis = calculate(time);
|
||||
mNode->setNodeMask(vis ? ~0 : 0);
|
||||
if (hasInput())
|
||||
{
|
||||
bool vis = calculate(getInputValue(nv));
|
||||
node->setNodeMask(vis ? ~0 : 0);
|
||||
}
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
AlphaControllerValue::AlphaControllerValue(osg::StateSet *target, const Nif::NiFloatData *data)
|
||||
: mTarget(target)
|
||||
, mData(data->mKeyList)
|
||||
{
|
||||
}
|
||||
|
||||
void AlphaControllerValue::setValue(float time)
|
||||
{
|
||||
float value = interpKey(mData.mKeys, time);
|
||||
osg::Material* mat = dynamic_cast<osg::Material*>(mTarget->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
if (!mat)
|
||||
return;
|
||||
|
||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||
diffuse.a() = value;
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
|
||||
MaterialColorControllerValue::MaterialColorControllerValue(osg::StateSet *target, const Nif::NiPosData *data)
|
||||
: mTarget(target), mData(data->mKeyList)
|
||||
AlphaController::AlphaController(const Nif::NiFloatData *data)
|
||||
: mData(data->mKeyList)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MaterialColorControllerValue::setValue(float time)
|
||||
AlphaController::AlphaController()
|
||||
{
|
||||
osg::Vec3f value = interpKey(mData.mKeys, time);
|
||||
osg::Material* mat = dynamic_cast<osg::Material*>(mTarget->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
if (!mat)
|
||||
return;
|
||||
|
||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||
diffuse.set(value.x(), value.y(), value.z(), diffuse.a());
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
|
||||
FlipControllerValue::FlipControllerValue(osg::StateSet* target, const Nif::NiFlipController *ctrl,
|
||||
std::vector<osg::ref_ptr<osg::Image> > textures)
|
||||
AlphaController::AlphaController(const AlphaController ©, const osg::CopyOp ©op)
|
||||
: osg::NodeCallback(copy, copyop), ValueInterpolator(), Controller(copy)
|
||||
{
|
||||
}
|
||||
|
||||
void AlphaController::operator () (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (hasInput())
|
||||
{
|
||||
osg::StateSet* stateset = node->getStateSet();
|
||||
float value = interpKey(mData.mKeys, getInputValue(nv));
|
||||
osg::Material* mat = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
if (mat)
|
||||
{
|
||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||
diffuse.a() = value;
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
}
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
MaterialColorController::MaterialColorController(const Nif::NiPosData *data)
|
||||
: mData(data->mKeyList)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialColorController::MaterialColorController()
|
||||
{
|
||||
}
|
||||
|
||||
MaterialColorController::MaterialColorController(const MaterialColorController ©, const osg::CopyOp ©op)
|
||||
: osg::NodeCallback(copy, copyop), Controller(copy)
|
||||
, mData(copy.mData)
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialColorController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (hasInput())
|
||||
{
|
||||
osg::StateSet* stateset = node->getStateSet();
|
||||
osg::Vec3f value = interpKey(mData.mKeys, getInputValue(nv));
|
||||
osg::Material* mat = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
if (mat)
|
||||
{
|
||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||
diffuse.set(value.x(), value.y(), value.z(), diffuse.a());
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
}
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
FlipController::FlipController(const Nif::NiFlipController *ctrl, std::vector<osg::ref_ptr<osg::Image> > textures)
|
||||
: mTexSlot(ctrl->mTexSlot)
|
||||
, mDelta(ctrl->mDelta)
|
||||
, mTextures(textures)
|
||||
, mTarget(target)
|
||||
{
|
||||
}
|
||||
|
||||
void FlipControllerValue::setValue(float time)
|
||||
{
|
||||
if (mDelta == 0)
|
||||
return;
|
||||
int curTexture = int(time / mDelta) % mTextures.size();
|
||||
osg::Texture2D* tex = dynamic_cast<osg::Texture2D*>(mTarget->getAttribute(osg::StateAttribute::TEXTURE));
|
||||
if (!tex)
|
||||
return;
|
||||
tex->setImage(mTextures[curTexture].get());
|
||||
}
|
||||
|
||||
ParticleSystemControllerValue::ParticleSystemControllerValue(osgParticle::Emitter *emitter, const Nif::NiParticleSystemController *ctrl)
|
||||
: mEmitter(emitter), mEmitStart(ctrl->startTime), mEmitStop(ctrl->stopTime)
|
||||
FlipController::FlipController()
|
||||
{
|
||||
}
|
||||
|
||||
void ParticleSystemControllerValue::setValue(float time)
|
||||
FlipController::FlipController(const FlipController ©, const osg::CopyOp ©op)
|
||||
: osg::NodeCallback(copy, copyop)
|
||||
, Controller(copy)
|
||||
, mTexSlot(copy.mTexSlot)
|
||||
, mDelta(copy.mDelta)
|
||||
, mTextures(copy.mTextures)
|
||||
{
|
||||
mEmitter->setEnabled(time >= mEmitStart && time < mEmitStop);
|
||||
}
|
||||
|
||||
void FlipController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (hasInput() && mDelta != 0)
|
||||
{
|
||||
osg::StateSet* stateset = node->getStateSet();
|
||||
int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size();
|
||||
osg::Texture2D* tex = dynamic_cast<osg::Texture2D*>(stateset->getAttribute(osg::StateAttribute::TEXTURE));
|
||||
if (tex)
|
||||
tex->setImage(mTextures[curTexture].get());
|
||||
}
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
ParticleSystemController::ParticleSystemController(const Nif::NiParticleSystemController *ctrl)
|
||||
: mEmitStart(ctrl->startTime), mEmitStop(ctrl->stopTime)
|
||||
{
|
||||
}
|
||||
|
||||
ParticleSystemController::ParticleSystemController()
|
||||
{
|
||||
}
|
||||
|
||||
ParticleSystemController::ParticleSystemController(const ParticleSystemController ©, const osg::CopyOp ©op)
|
||||
: osg::NodeCallback(copy, copyop)
|
||||
, Controller(copy)
|
||||
, mEmitStart(copy.mEmitStart)
|
||||
, mEmitStop(copy.mEmitStop)
|
||||
{
|
||||
}
|
||||
|
||||
void ParticleSystemController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
if (hasInput())
|
||||
{
|
||||
osgParticle::ParticleProcessor* emitter = dynamic_cast<osgParticle::ParticleProcessor*>(node);
|
||||
float time = getInputValue(nv);
|
||||
if (emitter)
|
||||
emitter->setEnabled(time >= mEmitStart && time < mEmitStop);
|
||||
}
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <osg/Timer>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/NodeCallback>
|
||||
#include <osg/Drawable>
|
||||
|
||||
|
||||
namespace osg
|
||||
@ -93,76 +96,49 @@ namespace NifOsg
|
||||
class ControllerSource
|
||||
{
|
||||
public:
|
||||
virtual float getValue() const = 0;
|
||||
virtual float getValue(osg::NodeVisitor* nv) = 0;
|
||||
};
|
||||
|
||||
// FIXME: Should return a dt instead of time
|
||||
class FrameTimeSource : public ControllerSource
|
||||
{
|
||||
public:
|
||||
|
||||
virtual float getValue() const
|
||||
{
|
||||
return mTimer.time_s();
|
||||
}
|
||||
|
||||
FrameTimeSource();
|
||||
virtual float getValue(osg::NodeVisitor* nv);
|
||||
private:
|
||||
osg::Timer mTimer;
|
||||
};
|
||||
|
||||
class ControllerValue
|
||||
{
|
||||
public:
|
||||
virtual void setValue(float value) = 0;
|
||||
double mLastTime;
|
||||
};
|
||||
|
||||
class Controller
|
||||
{
|
||||
public:
|
||||
Controller (boost::shared_ptr<ControllerSource> src, boost::shared_ptr<ControllerValue> dest,
|
||||
boost::shared_ptr<ControllerFunction> function);
|
||||
Controller();
|
||||
|
||||
virtual void update();
|
||||
bool hasInput() const;
|
||||
|
||||
float getInputValue(osg::NodeVisitor* nv);
|
||||
|
||||
boost::shared_ptr<ControllerSource> mSource;
|
||||
boost::shared_ptr<ControllerValue> mDestValue;
|
||||
|
||||
// The source value gets passed through this function before it's passed on to the DestValue.
|
||||
boost::shared_ptr<ControllerFunction> mFunction;
|
||||
};
|
||||
|
||||
// FIXME: Should be with other general extensions.
|
||||
class NodeTargetValue : public ControllerValue
|
||||
{
|
||||
protected:
|
||||
// TODO: get rid of target pointers, which are incompatible with a copy constructor we will need later
|
||||
// instead, controllers can be a Node added as child of their target
|
||||
osg::Node *mNode;
|
||||
|
||||
public:
|
||||
NodeTargetValue(osg::Node *target) : mNode(target)
|
||||
{ }
|
||||
|
||||
virtual osg::Vec3f getTranslation(float value) const = 0;
|
||||
|
||||
osg::Node *getNode() const
|
||||
{ return mNode; }
|
||||
};
|
||||
|
||||
class GeomMorpherControllerValue : public ControllerValue, public ValueInterpolator
|
||||
class GeomMorpherController : public osg::Drawable::UpdateCallback, public Controller, public ValueInterpolator
|
||||
{
|
||||
public:
|
||||
// FIXME: don't copy the morph data?
|
||||
GeomMorpherControllerValue(osgAnimation::MorphGeometry* geom, const Nif::NiMorphData *data);
|
||||
GeomMorpherController(const Nif::NiMorphData* data);
|
||||
GeomMorpherController();
|
||||
GeomMorpherController(const GeomMorpherController& copy, const osg::CopyOp& copyop);
|
||||
|
||||
virtual void setValue(float time);
|
||||
META_Object(NifOsg, GeomMorpherController)
|
||||
|
||||
virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable);
|
||||
|
||||
private:
|
||||
osgAnimation::MorphGeometry* mGeom;
|
||||
std::vector<Nif::NiMorphData::MorphData> mMorphs;
|
||||
};
|
||||
|
||||
class KeyframeControllerValue : public NodeTargetValue, public ValueInterpolator
|
||||
class KeyframeController : public osg::NodeCallback, public Controller, public ValueInterpolator
|
||||
{
|
||||
private:
|
||||
const Nif::QuaternionKeyMap* mRotations;
|
||||
@ -185,31 +161,39 @@ namespace NifOsg
|
||||
|
||||
public:
|
||||
/// @note The NiKeyFrameData must be valid as long as this KeyframeController exists.
|
||||
KeyframeControllerValue(osg::Node *target, const Nif::NIFFilePtr& nif, const Nif::NiKeyframeData *data,
|
||||
KeyframeController(const Nif::NIFFilePtr& nif, const Nif::NiKeyframeData *data,
|
||||
osg::Quat initialQuat, float initialScale);
|
||||
KeyframeController();
|
||||
KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop);
|
||||
|
||||
META_Object(NifOsg, KeyframeController)
|
||||
|
||||
virtual osg::Vec3f getTranslation(float time) const;
|
||||
|
||||
virtual void setValue(float time);
|
||||
virtual void operator() (osg::Node*, osg::NodeVisitor*);
|
||||
};
|
||||
|
||||
class UVControllerValue : public ControllerValue, ValueInterpolator
|
||||
// Note we're using NodeCallback instead of StateSet::Callback because the StateSet callback doesn't support nesting
|
||||
struct UVController : public osg::NodeCallback, public Controller, public ValueInterpolator
|
||||
{
|
||||
public:
|
||||
UVController();
|
||||
UVController(const UVController&,const osg::CopyOp& = osg::CopyOp::SHALLOW_COPY);
|
||||
UVController(const Nif::NiUVData *data, std::set<int> textureUnits);
|
||||
|
||||
META_Object(NifOsg,UVController)
|
||||
|
||||
virtual void operator() (osg::Node*, osg::NodeVisitor*);
|
||||
|
||||
private:
|
||||
osg::StateSet* mStateSet;
|
||||
Nif::FloatKeyMap mUTrans;
|
||||
Nif::FloatKeyMap mVTrans;
|
||||
Nif::FloatKeyMap mUScale;
|
||||
Nif::FloatKeyMap mVScale;
|
||||
std::set<int> mTextureUnits;
|
||||
|
||||
public:
|
||||
UVControllerValue(osg::StateSet* target, const Nif::NiUVData *data, std::set<int> textureUnits);
|
||||
|
||||
virtual void setValue(float value);
|
||||
};
|
||||
|
||||
class VisControllerValue : public NodeTargetValue
|
||||
class VisController : public osg::NodeCallback, public Controller
|
||||
{
|
||||
private:
|
||||
std::vector<Nif::NiVisData::VisData> mData;
|
||||
@ -217,65 +201,75 @@ namespace NifOsg
|
||||
bool calculate(float time) const;
|
||||
|
||||
public:
|
||||
VisControllerValue(osg::Node *target, const Nif::NiVisData *data)
|
||||
: NodeTargetValue(target)
|
||||
, mData(data->mVis)
|
||||
{ }
|
||||
VisController(const Nif::NiVisData *data);
|
||||
VisController();
|
||||
VisController(const VisController& copy, const osg::CopyOp& copyop);
|
||||
|
||||
virtual osg::Vec3f getTranslation(float time) const
|
||||
{ return osg::Vec3f(); }
|
||||
META_Object(NifOsg, VisController)
|
||||
|
||||
virtual void setValue(float time);
|
||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
|
||||
class AlphaControllerValue : public ControllerValue, public ValueInterpolator
|
||||
class AlphaController : public osg::NodeCallback, public Controller, public ValueInterpolator
|
||||
{
|
||||
private:
|
||||
osg::StateSet* mTarget;
|
||||
Nif::FloatKeyMap mData;
|
||||
|
||||
public:
|
||||
AlphaControllerValue(osg::StateSet* target, const Nif::NiFloatData *data);
|
||||
AlphaController(const Nif::NiFloatData *data);
|
||||
AlphaController();
|
||||
AlphaController(const AlphaController& copy, const osg::CopyOp& copyop);
|
||||
|
||||
virtual void setValue(float time);
|
||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
||||
|
||||
META_Object(NifOsg, AlphaController)
|
||||
};
|
||||
|
||||
class MaterialColorControllerValue : public ControllerValue, public ValueInterpolator
|
||||
class MaterialColorController : public osg::NodeCallback, public Controller, public ValueInterpolator
|
||||
{
|
||||
private:
|
||||
osg::StateSet* mTarget;
|
||||
Nif::Vector3KeyMap mData;
|
||||
|
||||
public:
|
||||
MaterialColorControllerValue(osg::StateSet* target, const Nif::NiPosData *data);
|
||||
MaterialColorController(const Nif::NiPosData *data);
|
||||
MaterialColorController();
|
||||
MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop);
|
||||
|
||||
virtual void setValue(float time);
|
||||
META_Object(NifOsg, MaterialColorController)
|
||||
|
||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
|
||||
// untested
|
||||
class FlipControllerValue : public ControllerValue
|
||||
class FlipController : public osg::NodeCallback, public Controller
|
||||
{
|
||||
private:
|
||||
osg::StateSet* mTarget;
|
||||
int mTexSlot;
|
||||
float mDelta;
|
||||
std::vector<osg::ref_ptr<osg::Image> > mTextures;
|
||||
|
||||
public:
|
||||
FlipControllerValue(osg::StateSet* target, const Nif::NiFlipController* ctrl, std::vector<osg::ref_ptr<osg::Image> > textures);
|
||||
FlipController(const Nif::NiFlipController* ctrl, std::vector<osg::ref_ptr<osg::Image> > textures);
|
||||
FlipController();
|
||||
FlipController(const FlipController& copy, const osg::CopyOp& copyop);
|
||||
|
||||
virtual void setValue(float time);
|
||||
META_Object(NifOsg, FlipController)
|
||||
|
||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
|
||||
class ParticleSystemControllerValue : public ControllerValue
|
||||
class ParticleSystemController : public osg::NodeCallback, public Controller
|
||||
{
|
||||
public:
|
||||
ParticleSystemControllerValue(osgParticle::Emitter* emitter, const Nif::NiParticleSystemController* ctrl);
|
||||
ParticleSystemController(const Nif::NiParticleSystemController* ctrl);
|
||||
ParticleSystemController();
|
||||
ParticleSystemController(const ParticleSystemController& copy, const osg::CopyOp& copyop);
|
||||
|
||||
virtual void setValue(float time);
|
||||
META_Object(NifOsg, ParticleSystemController)
|
||||
|
||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
||||
|
||||
private:
|
||||
osgParticle::Emitter* mEmitter;
|
||||
float mEmitStart;
|
||||
float mEmitStop;
|
||||
};
|
||||
|
@ -285,17 +285,13 @@ namespace NifOsg
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::createController(const Nif::Controller *ctrl, boost::shared_ptr<ControllerValue> value, int animflags)
|
||||
void Loader::setupController(const Nif::Controller* ctrl, Controller* toSetup, int animflags)
|
||||
{
|
||||
// FIXME animflags currently not passed to this function
|
||||
//bool autoPlay = animflags & Nif::NiNode::AnimFlag_AutoPlay;
|
||||
boost::shared_ptr<ControllerSource> src(new FrameTimeSource); // if autoPlay
|
||||
//if (autoPlay)
|
||||
toSetup->mSource = boost::shared_ptr<ControllerSource>(new FrameTimeSource);
|
||||
|
||||
boost::shared_ptr<ControllerFunction> function (new ControllerFunction(ctrl
|
||||
, 0/*autoPlay*/));
|
||||
//scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
|
||||
|
||||
mControllers.push_back(Controller(src, value, function));
|
||||
toSetup->mFunction = boost::shared_ptr<ControllerFunction>(new ControllerFunction(ctrl, 1 /*autoPlay*/));
|
||||
}
|
||||
|
||||
void Loader::handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton,
|
||||
@ -308,7 +304,6 @@ namespace NifOsg
|
||||
transformNode = bone;
|
||||
bone->setMatrix(toMatrix(nifNode->trafo));
|
||||
bone->setName(nifNode->name);
|
||||
bone->setUpdateCallback(new UpdateBone);
|
||||
bone->setInvBindMatrixInSkeletonSpace(osg::Matrixf::inverse(getWorldTransform(nifNode)));
|
||||
}
|
||||
else
|
||||
@ -332,6 +327,7 @@ namespace NifOsg
|
||||
|
||||
// We could probably skip hidden nodes entirely if they don't have a VisController that
|
||||
// might make them visible later
|
||||
// FIXME: this disables update callbacks, so VisController no longer works
|
||||
if (nifNode->flags & Nif::NiNode::Flag_Hidden)
|
||||
transformNode->setNodeMask(0);
|
||||
|
||||
@ -358,6 +354,10 @@ namespace NifOsg
|
||||
if (!nifNode->controller.empty())
|
||||
handleNodeControllers(nifNode, transformNode, animflags);
|
||||
|
||||
// Added last so the changes from KeyframeControllers are taken into account
|
||||
if (osgAnimation::Bone* bone = dynamic_cast<osgAnimation::Bone*>(transformNode.get()))
|
||||
bone->addUpdateCallback(new UpdateBone);
|
||||
|
||||
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
|
||||
if(ninode)
|
||||
{
|
||||
@ -382,9 +382,12 @@ namespace NifOsg
|
||||
std::set<int> texUnits;
|
||||
for (std::map<int, int>::const_iterator it = boundTextures.begin(); it != boundTextures.end(); ++it)
|
||||
texUnits.insert(it->first);
|
||||
boost::shared_ptr<ControllerValue> dest(new UVControllerValue(transformNode->getOrCreateStateSet()
|
||||
, uvctrl->data.getPtr(), texUnits));
|
||||
createController(uvctrl, dest, animflags);
|
||||
|
||||
osg::ref_ptr<UVController> ctrl = new UVController(uvctrl->data.getPtr(), texUnits);
|
||||
setupController(uvctrl, ctrl, animflags);
|
||||
transformNode->getOrCreateStateSet()->setDataVariance(osg::StateSet::DYNAMIC);
|
||||
|
||||
transformNode->addUpdateCallback(ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -406,23 +409,27 @@ namespace NifOsg
|
||||
std::cerr << "Warning: multiple KeyframeControllers on the same node" << std::endl;
|
||||
continue;
|
||||
}
|
||||
boost::shared_ptr<ControllerValue> dest(new KeyframeControllerValue(transformNode, mNif, key->data.getPtr(),
|
||||
transformNode->getMatrix().getRotate(), nifNode->trafo.scale));
|
||||
osg::ref_ptr<KeyframeController> callback(new KeyframeController(mNif, key->data.getPtr(),
|
||||
transformNode->getMatrix().getRotate(), nifNode->trafo.scale));
|
||||
|
||||
setupController(key, callback, animflags);
|
||||
transformNode->addUpdateCallback(callback);
|
||||
|
||||
createController(key, dest, animflags);
|
||||
seenKeyframeCtrl = true;
|
||||
}
|
||||
}
|
||||
else if (ctrl->recType == Nif::RC_NiVisController)
|
||||
{
|
||||
const Nif::NiVisController* visctrl = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
|
||||
boost::shared_ptr<ControllerValue> dest(new VisControllerValue(transformNode, visctrl->data.getPtr()));
|
||||
createController(visctrl, dest, animflags);
|
||||
|
||||
osg::ref_ptr<VisController> callback(new VisController(visctrl->data.getPtr()));
|
||||
setupController(visctrl, callback, animflags);
|
||||
transformNode->addUpdateCallback(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::handleMaterialControllers(const Nif::Property *materialProperty, osg::StateSet *stateset, int animflags)
|
||||
void Loader::handleMaterialControllers(const Nif::Property *materialProperty, osg::Node* node, osg::StateSet *stateset, int animflags)
|
||||
{
|
||||
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
{
|
||||
@ -431,21 +438,25 @@ namespace NifOsg
|
||||
if (ctrl->recType == Nif::RC_NiAlphaController)
|
||||
{
|
||||
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
||||
boost::shared_ptr<ControllerValue> dest(new AlphaControllerValue(stateset, alphactrl->data.getPtr()));
|
||||
createController(alphactrl, dest, animflags);
|
||||
osg::ref_ptr<AlphaController> ctrl(new AlphaController(alphactrl->data.getPtr()));
|
||||
setupController(alphactrl, ctrl, animflags);
|
||||
stateset->setDataVariance(osg::StateSet::DYNAMIC);
|
||||
node->addUpdateCallback(ctrl);
|
||||
}
|
||||
else if (ctrl->recType == Nif::RC_NiMaterialColorController)
|
||||
{
|
||||
const Nif::NiMaterialColorController* matctrl = static_cast<const Nif::NiMaterialColorController*>(ctrl.getPtr());
|
||||
boost::shared_ptr<ControllerValue> dest(new MaterialColorControllerValue(stateset, matctrl->data.getPtr()));
|
||||
createController(matctrl, dest, animflags);
|
||||
osg::ref_ptr<MaterialColorController> ctrl(new MaterialColorController(matctrl->data.getPtr()));
|
||||
setupController(matctrl, ctrl, animflags);
|
||||
stateset->setDataVariance(osg::StateSet::DYNAMIC);
|
||||
node->addUpdateCallback(ctrl);
|
||||
}
|
||||
else
|
||||
std::cerr << "Unexpected material controller " << ctrl->recType << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::handleTextureControllers(const Nif::Property *texProperty, osg::StateSet *stateset, int animflags)
|
||||
void Loader::handleTextureControllers(const Nif::Property *texProperty, osg::Node* node, osg::StateSet *stateset, int animflags)
|
||||
{
|
||||
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
{
|
||||
@ -470,8 +481,10 @@ namespace NifOsg
|
||||
osgDB::ReaderWriter::ReadResult result = reader->readImage(*resourceManager->get(filename.c_str()), opts);
|
||||
textures.push_back(osg::ref_ptr<osg::Image>(result.getImage()));
|
||||
}
|
||||
boost::shared_ptr<ControllerValue> dest(new FlipControllerValue(stateset, flipctrl, textures));
|
||||
createController(flipctrl, dest, animflags);
|
||||
osg::ref_ptr<FlipController> callback(new FlipController(flipctrl, textures));
|
||||
setupController(ctrl.getPtr(), callback, animflags);
|
||||
stateset->setDataVariance(osg::StateSet::DYNAMIC);
|
||||
node->addUpdateCallback(callback);
|
||||
}
|
||||
else
|
||||
std::cerr << "Unexpected texture controller " << ctrl->recName << std::endl;
|
||||
@ -577,7 +590,9 @@ namespace NifOsg
|
||||
// If something ever violates this assumption, the worst that could happen is the culling being one frame late, which wouldn't be a disaster.
|
||||
parentNode->addChild(emitter);
|
||||
|
||||
createController(partctrl, boost::shared_ptr<ControllerValue>(new ParticleSystemControllerValue(emitter, partctrl)), animflags);
|
||||
osg::ref_ptr<ParticleSystemController> callback(new ParticleSystemController(partctrl));
|
||||
setupController(partctrl, callback, animflags);
|
||||
emitter->setUpdateCallback(callback);
|
||||
|
||||
// ----------- affector (must be after emitters in the scene graph)
|
||||
osgParticle::ModularProgram* program = new osgParticle::ModularProgram;
|
||||
@ -615,14 +630,16 @@ namespace NifOsg
|
||||
|
||||
// -----------
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(partsys);
|
||||
|
||||
std::vector<const Nif::Property*> materialProps;
|
||||
collectMaterialProperties(nifNode, materialProps);
|
||||
applyMaterialProperties(partsys->getOrCreateStateSet(), materialProps, true, animflags);
|
||||
applyMaterialProperties(geode, materialProps, true, animflags);
|
||||
|
||||
partsys->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
partsys->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(partsys);
|
||||
|
||||
|
||||
if (rf == osgParticle::ParticleProcessor::RELATIVE_RF)
|
||||
parentNode->addChild(geode);
|
||||
@ -640,7 +657,7 @@ namespace NifOsg
|
||||
parentNode->addChild(updater);
|
||||
}
|
||||
|
||||
void Loader::triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, const std::map<int, int>& boundTextures, int animflags)
|
||||
void Loader::triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, osg::Geode* parentGeode, const std::map<int, int>& boundTextures, int animflags)
|
||||
{
|
||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||
|
||||
@ -720,7 +737,7 @@ namespace NifOsg
|
||||
// above the actual renderable would be tedious.
|
||||
std::vector<const Nif::Property*> materialProps;
|
||||
collectMaterialProperties(triShape, materialProps);
|
||||
applyMaterialProperties(geometry->getOrCreateStateSet(), materialProps, !data->colors.empty(), animflags);
|
||||
applyMaterialProperties(parentGeode, materialProps, !data->colors.empty(), animflags);
|
||||
}
|
||||
|
||||
void Loader::handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures, int animflags)
|
||||
@ -733,10 +750,11 @@ namespace NifOsg
|
||||
if(ctrl->recType == Nif::RC_NiGeomMorpherController && ctrl->flags & Nif::NiNode::ControllerFlag_Active)
|
||||
{
|
||||
geometry = handleMorphGeometry(static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr()));
|
||||
boost::shared_ptr<ControllerValue> value(
|
||||
new GeomMorpherControllerValue(static_cast<osgAnimation::MorphGeometry*>(geometry.get()),
|
||||
static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr())->data.getPtr()));
|
||||
createController(ctrl.getPtr(), value, 0);
|
||||
|
||||
osg::ref_ptr<GeomMorpherController> morphctrl = new GeomMorpherController(
|
||||
static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr())->data.getPtr());
|
||||
setupController(ctrl.getPtr(), morphctrl, animflags);
|
||||
geometry->setUpdateCallback(morphctrl);
|
||||
break;
|
||||
}
|
||||
} while(!(ctrl=ctrl->next).empty());
|
||||
@ -744,9 +762,10 @@ namespace NifOsg
|
||||
|
||||
if (!geometry.get())
|
||||
geometry = new osg::Geometry;
|
||||
triShapeToGeometry(triShape, geometry, boundTextures, animflags);
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
triShapeToGeometry(triShape, geometry, geode, boundTextures, animflags);
|
||||
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
parentNode->addChild(geode);
|
||||
@ -754,8 +773,9 @@ namespace NifOsg
|
||||
|
||||
void Loader::handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, const std::map<int, int>& boundTextures, int animflags)
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||
triShapeToGeometry(triShape, geometry, boundTextures, animflags);
|
||||
triShapeToGeometry(triShape, geometry, geode, boundTextures, animflags);
|
||||
|
||||
osg::ref_ptr<osgAnimation::RigGeometry> rig(new osgAnimation::RigGeometry);
|
||||
rig->setSourceGeometry(geometry);
|
||||
@ -795,7 +815,6 @@ namespace NifOsg
|
||||
osg::ref_ptr<osg::MatrixTransform> trans(new osg::MatrixTransform);
|
||||
trans->setUpdateCallback(new InvertBoneMatrix());
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(rig);
|
||||
|
||||
trans->addChild(geode);
|
||||
@ -987,7 +1006,7 @@ namespace NifOsg
|
||||
stateset->setTextureAttributeAndModes(i, new osg::Texture2D, osg::StateAttribute::OFF);
|
||||
boundTextures.erase(i);
|
||||
}
|
||||
handleTextureControllers(texprop, stateset, animflags);
|
||||
handleTextureControllers(texprop, node, stateset, animflags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1003,9 +1022,11 @@ namespace NifOsg
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties,
|
||||
void Loader::applyMaterialProperties(osg::Node* node, const std::vector<const Nif::Property*>& properties,
|
||||
bool hasVertexColors, int animflags)
|
||||
{
|
||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||
|
||||
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
||||
osg::Material* mat = new osg::Material;
|
||||
mat->setColorMode(hasVertexColors ? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF);
|
||||
@ -1032,7 +1053,7 @@ namespace NifOsg
|
||||
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
||||
|
||||
if (!matprop->controller.empty())
|
||||
handleMaterialControllers(matprop, stateset, animflags);
|
||||
handleMaterialControllers(matprop, node, stateset, animflags);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
#include <osg/Group>
|
||||
|
||||
#include "controller.hpp"
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Geometry;
|
||||
@ -25,10 +23,12 @@ namespace Nif
|
||||
class Node;
|
||||
class NiTriShape;
|
||||
class Property;
|
||||
class Controller;
|
||||
}
|
||||
|
||||
namespace NifOsg
|
||||
{
|
||||
class Controller;
|
||||
|
||||
/// The main class responsible for loading NIF files into an OSG-Scenegraph.
|
||||
class Loader
|
||||
@ -41,9 +41,6 @@ namespace NifOsg
|
||||
|
||||
const VFS::Manager* resourceManager;
|
||||
|
||||
// FIXME move
|
||||
std::vector<Controller> mControllers;
|
||||
|
||||
private:
|
||||
|
||||
/// @param createSkeleton If true, use an osgAnimation::Bone for NIF nodes, otherwise an osg::MatrixTransform.
|
||||
@ -54,9 +51,9 @@ namespace NifOsg
|
||||
|
||||
void handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, int animflags);
|
||||
|
||||
void handleMaterialControllers(const Nif::Property* materialProperty, osg::StateSet* stateset, int animflags);
|
||||
void handleMaterialControllers(const Nif::Property* materialProperty, osg::Node* node, osg::StateSet* stateset, int animflags);
|
||||
|
||||
void handleTextureControllers(const Nif::Property* texProperty, osg::StateSet* stateset, int animflags);
|
||||
void handleTextureControllers(const Nif::Property* texProperty, osg::Node* node, osg::StateSet* stateset, int animflags);
|
||||
|
||||
void handleProperty (const Nif::Property* property, const Nif::Node* nifNode,
|
||||
osg::Node* node, std::map<int, int>& boundTextures, int animflags);
|
||||
@ -67,7 +64,7 @@ namespace NifOsg
|
||||
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures, int animflags);
|
||||
|
||||
// Fills the vertex data for the given TriShape into the given Geometry.
|
||||
void triShapeToGeometry(const Nif::NiTriShape* triShape, osg::Geometry* geom, const std::map<int, int>& boundTextures, int animflags);
|
||||
void triShapeToGeometry(const Nif::NiTriShape* triShape, osg::Geometry* geom, osg::Geode* parentGeode, const std::map<int, int>& boundTextures, int animflags);
|
||||
|
||||
// Creates a skinned osg::Geometry object for the given TriShape, populates it, and attaches it to the given node.
|
||||
void handleSkinnedTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures, int animflags);
|
||||
@ -75,10 +72,11 @@ namespace NifOsg
|
||||
// Applies the Properties of the given nifNode onto the StateSet of the given OSG node.
|
||||
void applyNodeProperties(const Nif::Node* nifNode, osg::Node* applyTo, std::map<int, int>& boundTextures, int animflags);
|
||||
|
||||
void applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties,
|
||||
void applyMaterialProperties(osg::Node* node, const std::vector<const Nif::Property*>& properties,
|
||||
bool hasVertexColors, int animflags);
|
||||
|
||||
void createController(const Nif::Controller* ctrl, boost::shared_ptr<ControllerValue> value, int animflags);
|
||||
// Set up the default input and controller function for the given controller.
|
||||
void setupController(const Nif::Controller* ctrl, Controller* toSetup, int animflags);
|
||||
|
||||
Nif::NIFFilePtr mNif;
|
||||
|
||||
|
@ -39,6 +39,7 @@ ParticleShooter::ParticleShooter()
|
||||
}
|
||||
|
||||
ParticleShooter::ParticleShooter(const osgParticle::Shooter ©, const osg::CopyOp ©op)
|
||||
: osgParticle::Shooter(copy, copyop)
|
||||
{
|
||||
*this = copy;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user