Merge remote-tracking branch 'scrawl/master' into openmw-37

pull/802/head
Marc Zinnschlag 9 years ago
commit 77b325a1db

2
.gitignore vendored

@ -5,7 +5,7 @@ CMakeCache.txt
cmake_install.cmake
Makefile
makefile
build
build*
prebuilt
## doxygen

@ -1479,6 +1479,8 @@ bool CharacterController::updateWeaponState()
}
}
mAnimation->setAccurateAiming(mUpperBodyState > UpperCharState_WeapEquiped);
return forcestateupdate;
}

@ -11,8 +11,8 @@
namespace MWMechanics
{
// NOTE: determined empirically but probably need further tweaking
static const float DIST_SAME_SPOT = 1.8f;
static const float DURATION_SAME_SPOT = 1.0f;
static const float DIST_SAME_SPOT = 0.5f;
static const float DURATION_SAME_SPOT = 1.5f;
static const float DURATION_TO_EVADE = 0.4f;
const float ObstacleCheck::evadeDirections[NUM_EVADE_DIRECTIONS][2] =
@ -114,20 +114,23 @@ namespace MWMechanics
* t = how long before considered stuck
* u = how long to move sideways
*
* DIST_SAME_SPOT is calibrated for movement speed of around 150.
* A rat has walking speed of around 30, so we need to adjust for
* that.
*/
bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration)
{
const MWWorld::Class& cls = actor.getClass();
ESM::Position pos = actor.getRefData().getPosition();
// actors can move at most 60 fps (the physics framerate).
// the max() can be removed if we implement physics interpolation.
float movementDuration = std::max(1/60.f, duration);
if(mDistSameSpot == -1)
mDistSameSpot = DIST_SAME_SPOT * (cls.getSpeed(actor) / 150);
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor);
float distSameSpot = mDistSameSpot * movementDuration;
bool samePosition = (osg::Vec2f(pos.pos[0], pos.pos[1]) - osg::Vec2f(mPrevX, mPrevY)).length2() < distSameSpot * distSameSpot;
bool samePosition = (std::abs(pos.pos[0] - mPrevX) < mDistSameSpot) &&
(std::abs(pos.pos[1] - mPrevY) < mDistSameSpot);
// update position
mPrevX = pos.pos[0];
mPrevY = pos.pos[1];
@ -160,13 +163,13 @@ namespace MWMechanics
{
mStuckDuration = 0;
mWalkState = State_Evade;
chooseEvasionDirection();
}
}
}
/* FALL THROUGH */
case State_Evade:
{
chooseEvasionDirection(samePosition);
mEvadeDuration += duration;
if(mEvadeDuration < DURATION_TO_EVADE)
return true;
@ -188,16 +191,13 @@ namespace MWMechanics
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1];
}
void ObstacleCheck::chooseEvasionDirection(bool samePosition)
void ObstacleCheck::chooseEvasionDirection()
{
// change direction if attempt didn't work
if (samePosition && (0 < mEvadeDuration))
++mEvadeDirectionIndex;
if (mEvadeDirectionIndex == NUM_EVADE_DIRECTIONS)
{
++mEvadeDirectionIndex;
if (mEvadeDirectionIndex == NUM_EVADE_DIRECTIONS)
{
mEvadeDirectionIndex = 0;
}
mEvadeDirectionIndex = 0;
}
}

@ -65,7 +65,7 @@ namespace MWMechanics
float mDistSameSpot; // take account of actor's speed
int mEvadeDirectionIndex;
void chooseEvasionDirection(bool samePosition);
void chooseEvasionDirection();
};
}

@ -11,6 +11,7 @@
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Material>
#include <osg/Version>
#include <osgParticle/ParticleSystem>
@ -174,72 +175,93 @@ namespace
return 0.0f;
}
/// @brief Base class for visitors that remove nodes from a scene graph.
/// Subclasses need to fill the mToRemove vector.
/// To use, node->accept(removeVisitor); removeVisitor.remove();
class RemoveVisitor : public osg::NodeVisitor
{
public:
RemoveVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
{
}
void remove()
{
for (RemoveVec::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
it->second->removeChild(it->first);
}
protected:
// <node to remove, parent node to remove it from>
typedef std::vector<std::pair<osg::Node*, osg::Group*> > RemoveVec;
std::vector<std::pair<osg::Node*, osg::Group*> > mToRemove;
};
// Removes all drawables from a graph.
class RemoveDrawableVisitor : public osg::NodeVisitor
class RemoveDrawableVisitor : public RemoveVisitor
{
public:
RemoveDrawableVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
virtual void apply(osg::Geode &geode)
{
applyImpl(geode);
}
virtual void apply(osg::Geode &node)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
virtual void apply(osg::Drawable& drw)
{
// Not safe to remove in apply(), since the visitor is still iterating the child list
osg::Group* parent = node.getParent(0);
// prune nodes that would be empty after the removal
if (parent->getNumChildren() == 1 && parent->getDataVariance() == osg::Object::STATIC)
mToRemove.push_back(parent);
else
mToRemove.push_back(&node);
traverse(node);
applyImpl(drw);
}
#endif
void remove()
void applyImpl(osg::Node& node)
{
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
osg::NodePath::iterator parent = getNodePath().end()-2;
// We know that the parent is a Group because only Groups can have children.
osg::Group* parentGroup = static_cast<osg::Group*>(*parent);
// Try to prune nodes that would be empty after the removal
if (parent != getNodePath().begin())
{
osg::Node* node = *it;
if (node->getNumParents())
node->getParent(0)->removeChild(node);
// This could be extended to remove the parent's parent, and so on if they are empty as well.
// But for NIF files, there won't be a benefit since only TriShapes can be set to STATIC dataVariance.
osg::Group* parentParent = static_cast<osg::Group*>(*(parent - 1));
if (parentGroup->getNumChildren() == 1 && parentGroup->getDataVariance() == osg::Object::STATIC)
{
mToRemove.push_back(std::make_pair(parentGroup, parentParent));
return;
}
}
}
private:
std::vector<osg::Node*> mToRemove;
mToRemove.push_back(std::make_pair(&node, parentGroup));
}
};
class RemoveTriBipVisitor : public osg::NodeVisitor
class RemoveTriBipVisitor : public RemoveVisitor
{
public:
RemoveTriBipVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
virtual void apply(osg::Geode &node)
{
applyImpl(node);
}
virtual void apply(osg::Geode &node)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
virtual void apply(osg::Drawable& drw)
{
const std::string toFind = "tri bip";
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
{
// Not safe to remove in apply(), since the visitor is still iterating the child list
mToRemove.push_back(&node);
}
applyImpl(drw);
}
#endif
void remove()
void applyImpl(osg::Node& node)
{
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
const std::string toFind = "tri bip";
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
{
osg::Node* node = *it;
if (node->getNumParents())
node->getParent(0)->removeChild(node);
osg::Group* parent = static_cast<osg::Group*>(*(getNodePath().end()-2));
// Not safe to remove in apply(), since the visitor is still iterating the child list
mToRemove.push_back(std::make_pair(&node, parent));
}
}
private:
std::vector<osg::Node*> mToRemove;
};
}
@ -1066,6 +1088,7 @@ namespace MWRender
osg::ref_ptr<SceneUtil::LightSource> lightSource = new SceneUtil::LightSource;
osg::Light* light = new osg::Light;
lightSource->setLight(light);
lightSource->setNodeMask(Mask_Lighting);
const MWWorld::Fallback* fallback = MWBase::Environment::get().getWorld()->getFallback();
@ -1294,6 +1317,7 @@ namespace MWRender
{
mGlowLight = new SceneUtil::LightSource;
mGlowLight->setLight(new osg::Light);
mGlowLight->setNodeMask(Mask_Lighting);
osg::Light* light = mGlowLight->getLight();
light->setDiffuse(osg::Vec4f(0,0,0,0));
light->setSpecular(osg::Vec4f(0,0,0,0));

@ -61,6 +61,9 @@ public:
private:
osg::ref_ptr<osg::Node> mNode;
void operator= (const PartHolder&);
PartHolder(const PartHolder&);
};
typedef boost::shared_ptr<PartHolder> PartHolderPtr;
@ -439,6 +442,7 @@ public:
virtual void setHeadYaw(float yawRadians);
virtual float getHeadPitch() const;
virtual float getHeadYaw() const;
virtual void setAccurateAiming(bool enabled) {}
private:
Animation(const Animation&);

@ -42,7 +42,8 @@ namespace MWRender
{
Camera::Camera (osg::Camera* camera)
: mCamera(camera),
: mHeightScale(1.f),
mCamera(camera),
mAnimation(NULL),
mFirstPersonView(true),
mPreviewMode(false),
@ -93,7 +94,7 @@ namespace MWRender
osg::Vec3d position = worldMat.getTrans();
if (!isFirstPerson())
position.z() += mHeight;
position.z() += mHeight * mHeightScale;
return position;
}
@ -372,11 +373,17 @@ namespace MWRender
mTrackingNode = mAnimation->getNode("Camera");
if (!mTrackingNode)
mTrackingNode = mAnimation->getNode("Head");
mHeightScale = 1.f;
}
else
{
mAnimation->setViewMode(NpcAnimation::VM_Normal);
mTrackingNode = mTrackingPtr.getRefData().getBaseNode();
osg::PositionAttitudeTransform* transform = mTrackingPtr.getRefData().getBaseNode();
mTrackingNode = transform;
if (transform)
mHeightScale = transform->getScale().z();
else
mHeightScale = 1.f;
}
rotateCamera(getPitch(), getYaw(), false);
}

@ -29,6 +29,7 @@ namespace MWRender
MWWorld::Ptr mTrackingPtr;
osg::ref_ptr<const osg::Node> mTrackingNode;
float mHeightScale;
osg::ref_ptr<osg::Camera> mCamera;

@ -157,11 +157,10 @@ namespace MWRender
void CharacterPreview::rebuild()
{
delete mAnimation;
mAnimation = NULL;
mAnimation.reset(NULL);
mAnimation = new NpcAnimation(mCharacter, mNode, mResourceSystem, true, true,
(renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
mAnimation.reset(new NpcAnimation(mCharacter, mNode, mResourceSystem, true, true,
(renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)));
onSetup();
@ -194,7 +193,7 @@ namespace MWRender
void InventoryPreview::update()
{
if (!mAnimation)
if (!mAnimation.get())
return;
mAnimation->showWeapons(true);

@ -2,6 +2,7 @@
#define MWRENDER_CHARACTERPREVIEW_H
#include <osg/ref_ptr>
#include <memory>
#include <components/esm/loadnpc.hpp>
@ -61,7 +62,7 @@ namespace MWRender
MWWorld::Ptr mCharacter;
MWRender::NpcAnimation* mAnimation;
std::auto_ptr<MWRender::NpcAnimation> mAnimation;
osg::ref_ptr<osg::PositionAttitudeTransform> mNode;
std::string mCurrentAnimGroup;

@ -62,9 +62,8 @@ namespace
class CameraUpdateGlobalCallback : public osg::NodeCallback
{
public:
CameraUpdateGlobalCallback(osg::Camera* cam, MWRender::GlobalMap* parent)
CameraUpdateGlobalCallback(MWRender::GlobalMap* parent)
: mRendered(false)
, mCamera(cam)
, mParent(parent)
{
}
@ -73,7 +72,7 @@ namespace
{
if (mRendered)
{
mCamera->setNodeMask(0);
node->setNodeMask(0);
return;
}
@ -82,13 +81,12 @@ namespace
if (!mRendered)
{
mRendered = true;
mParent->markForRemoval(mCamera);
mParent->markForRemoval(static_cast<osg::Camera*>(node));
}
}
private:
bool mRendered;
osg::ref_ptr<osg::Camera> mCamera;
MWRender::GlobalMap* mParent;
};
@ -263,11 +261,14 @@ namespace MWRender
else
camera->setClearMask(GL_NONE);
camera->setUpdateCallback(new CameraUpdateGlobalCallback(camera, this));
camera->setUpdateCallback(new CameraUpdateGlobalCallback(this));
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
camera->attach(osg::Camera::COLOR_BUFFER, mOverlayTexture);
// no need for a depth buffer
camera->setImplicitBufferAttachmentMask(osg::DisplaySettings::IMPLICIT_COLOR_BUFFER_ATTACHMENT);
if (cpuCopy)
{
// Attach an image to copy the render back to the CPU when finished
@ -288,10 +289,12 @@ namespace MWRender
{
osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(srcLeft, srcTop, srcRight, srcBottom);
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setFunction(osg::Depth::ALWAYS);
geom->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
geom->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
geom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
depth->setWriteMask(0);
osg::StateSet* stateset = geom->getOrCreateStateSet();
stateset->setAttribute(depth);
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(geom);
camera->addChild(geode);

@ -30,22 +30,21 @@ namespace
class CameraLocalUpdateCallback : public osg::NodeCallback
{
public:
CameraLocalUpdateCallback(osg::Camera* cam, MWRender::LocalMap* parent)
CameraLocalUpdateCallback(MWRender::LocalMap* parent)
: mRendered(false)
, mCamera(cam)
, mParent(parent)
{
}
virtual void operator()(osg::Node*, osg::NodeVisitor*)
virtual void operator()(osg::Node* node, osg::NodeVisitor*)
{
if (mRendered)
mCamera->setNodeMask(0);
node->setNodeMask(0);
if (!mRendered)
{
mRendered = true;
mParent->markForRemoval(mCamera);
mParent->markForRemoval(static_cast<osg::Camera*>(node));
}
// Note, we intentionally do not traverse children here. The map camera's scene data is the same as the master camera's,
@ -55,7 +54,6 @@ namespace
private:
bool mRendered;
osg::ref_ptr<osg::Camera> mCamera;
MWRender::LocalMap* mParent;
};
@ -205,7 +203,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
camera->setStateSet(stateset);
camera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
camera->setViewport(0, 0, mMapResolution, mMapResolution);
camera->setUpdateCallback(new CameraLocalUpdateCallback(camera, this));
camera->setUpdateCallback(new CameraLocalUpdateCallback(this));
return camera;
}

@ -281,7 +281,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> par
mShowWeapons(false),
mShowCarriedLeft(true),
mNpcType(Type_Normal),
mSoundsDisabled(disableSounds)
mSoundsDisabled(disableSounds),
mAccurateAiming(false),
mAimingFactor(0.f)
{
mNpc = mPtr.get<ESM::NPC>()->mBase;
@ -726,7 +728,14 @@ osg::Vec3f NpcAnimation::runAnimation(float timepassed)
if (mFirstPersonNeckController)
{
mFirstPersonNeckController->setRotate(osg::Quat(mPtr.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0)));
if (mAccurateAiming)
mAimingFactor = 1.f;
else
mAimingFactor = std::max(0.f, mAimingFactor - timepassed * 0.5f);
float rotateFactor = 0.75f + 0.25f * mAimingFactor;
mFirstPersonNeckController->setRotate(osg::Quat(mPtr.getRefData().getPosition().rot[0] * rotateFactor, osg::Vec3f(-1,0,0)));
mFirstPersonNeckController->setOffset(mFirstPersonOffset);
}
@ -1072,4 +1081,9 @@ void NpcAnimation::updatePtr(const MWWorld::Ptr &updated)
mHeadAnimationTime->updatePtr(updated);
}
void NpcAnimation::setAccurateAiming(bool enabled)
{
mAccurateAiming = enabled;
}
}

@ -67,6 +67,9 @@ private:
bool mSoundsDisabled;
bool mAccurateAiming;
float mAimingFactor;
void updateNpcBase();
PartHolderPtr insertBoundedPart(const std::string &model, const std::string &bonename,
@ -104,6 +107,10 @@ public:
virtual void enableHeadAnimation(bool enable);
/// 1: the first person meshes follow the camera's rotation completely
/// 0: the first person meshes follow the camera with a reduced factor, so you can look down at your own hands
virtual void setAccurateAiming(bool enabled);
virtual void setWeaponGroup(const std::string& group);
virtual osg::Vec3f runAnimation(float timepassed);

@ -6,6 +6,7 @@
#include <osg/Geode>
#include <osg/PositionAttitudeTransform>
#include <osg/UserDataContainer>
#include <osg/Version>
#include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleProcessor>
@ -54,11 +55,19 @@ namespace
for (std::vector<osgParticle::ParticleSystem*>::iterator it = partsysVector.begin(); it != partsysVector.end(); ++it)
geode.removeDrawable(*it);
}
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
virtual void apply(osg::Drawable& drw)
{
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
mToRemove.push_back(partsys);
}
#endif
void remove()
{
for (std::vector<osg::ref_ptr<osg::Node> >::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
{
// FIXME: a Drawable might have more than one parent
osg::Node* node = *it;
if (node->getNumParents())
node->getParent(0)->removeChild(node);

@ -137,7 +137,10 @@ namespace MWRender
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
, mNightEyeFactor(0.f)
{
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
osg::ref_ptr<SceneUtil::LightManager> lightRoot = new SceneUtil::LightManager;
lightRoot->setLightingMask(Mask_Lighting);
mLightRoot = lightRoot;
lightRoot->setStartLight(1);
@ -163,7 +166,7 @@ namespace MWRender
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
source->setNodeMask(SceneUtil::Mask_Lit);
source->setNodeMask(Mask_Lighting);
mSunLight = new osg::Light;
source->setLight(mSunLight);
mSunLight->setDiffuse(osg::Vec4f(0,0,0,1));
@ -439,6 +442,9 @@ namespace MWRender
void RenderingManager::scaleObject(const MWWorld::Ptr &ptr, const osg::Vec3f &scale)
{
ptr.getRefData().getBaseNode()->setScale(scale);
if (ptr == mCamera->getTrackingPtr()) // update height of camera
mCamera->processViewChange();
}
void RenderingManager::removeObject(const MWWorld::Ptr &ptr)

@ -27,7 +27,7 @@ protected:
bool mEnabled;
osg::Quat mRotate;
osg::ref_ptr<osg::Node> mRelativeTo;
osg::Node* mRelativeTo;
};

@ -351,33 +351,36 @@ public:
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
{
osg::Drawable* drw = geode.getDrawable(i);
apply(*drw);
}
}
void apply(osg::Drawable& drw)
{
osg::Geometry* geom = drw.asGeometry();
if (!geom)
return;
osg::Geometry* geom = drw->asGeometry();
if (!geom)
continue;
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements());
for (unsigned int i=0; i<colors->size(); ++i)
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements());
for (unsigned int i=0; i<colors->size(); ++i)
{
float alpha = 1.f;
if (mMeshType == 0) alpha = i%2 ? 0.f : 1.f; // this is a cylinder, so every second vertex belongs to the bottom-most row
else if (mMeshType == 1)
{
float alpha = 1.f;
if (mMeshType == 0) alpha = i%2 ? 0.f : 1.f; // this is a cylinder, so every second vertex belongs to the bottom-most row
else if (mMeshType == 1)
{
if (i>= 49 && i <= 64) alpha = 0.f; // bottom-most row
else if (i>= 33 && i <= 48) alpha = 0.25098; // second row
else alpha = 1.f;
}
else if (mMeshType == 2)
{
osg::Vec4Array* origColors = static_cast<osg::Vec4Array*>(geom->getColorArray());
alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f;
}
(*colors)[i] = osg::Vec4f(0.f, 0.f, 0.f, alpha);
if (i>= 49 && i <= 64) alpha = 0.f; // bottom-most row
else if (i>= 33 && i <= 48) alpha = 0.25098; // second row
else alpha = 1.f;
}
else if (mMeshType == 2)
{
osg::Vec4Array* origColors = static_cast<osg::Vec4Array*>(geom->getColorArray());
alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f;
}
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
(*colors)[i] = osg::Vec4f(0.f, 0.f, 0.f, alpha);
}
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
}
private:
@ -1268,7 +1271,7 @@ public:
if (stateset->getAttribute(osg::StateAttribute::MATERIAL))
{
SceneUtil::CompositeStateSetUpdater* composite = NULL;
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
osg::Callback* callback = node.getUpdateCallback();
#else
osg::NodeCallback* callback = node.getUpdateCallback();

@ -15,16 +15,16 @@ namespace MWRender
Mask_Actor = (1<<3),
Mask_Player = (1<<4),
Mask_Sky = (1<<5),
Mask_Water = (1<<6),
Mask_Terrain = (1<<7),
Mask_FirstPerson = (1<<8),
Mask_Water = (1<<6), // choose Water or SimpleWater depending on detail required
Mask_SimpleWater = (1<<7),
Mask_Terrain = (1<<8),
Mask_FirstPerson = (1<<9),
// child of Sky
Mask_Sun = (1<<9),
Mask_WeatherParticles = (1<<10),
Mask_Sun = (1<<10),
Mask_WeatherParticles = (1<<11),
// child of Water
Mask_SimpleWater = (1<<11),
// top level masks
Mask_Scene = (1<<12),
@ -34,9 +34,10 @@ namespace MWRender
Mask_ParticleSystem = (1<<14),
// Set on cameras within the main scene graph
Mask_RenderToTexture = (1<<15)
Mask_RenderToTexture = (1<<15),
// reserved: (1<<16) for SceneUtil::Mask_Lit
// Set on a camera's cull mask to enable the LightManager
Mask_Lighting = (1<<16)
};
}

@ -302,7 +302,7 @@ public:
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
setReferenceFrame(osg::Camera::RELATIVE_RF);
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|(1<<16));
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|Mask_Lighting);
setNodeMask(Mask_RenderToTexture);
setViewport(0, 0, rttSize, rttSize);
@ -378,7 +378,7 @@ public:
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
setReferenceFrame(osg::Camera::RELATIVE_RF);
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Player|(1<<16));
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Player|Mask_Lighting);
setNodeMask(Mask_RenderToTexture);
unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water");

@ -146,7 +146,7 @@ namespace NifOsg
{
public:
UVController();
UVController(const UVController&,const osg::CopyOp& = osg::CopyOp::SHALLOW_COPY);
UVController(const UVController&,const osg::CopyOp&);
UVController(const Nif::NiUVData *data, std::set<int> textureUnits);
META_Object(NifOsg,UVController)

@ -5,6 +5,7 @@
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Array>
#include <osg/Version>
// resource
#include <components/misc/stringops.hpp>
@ -536,7 +537,7 @@ namespace NifOsg
handleSkinnedTriShape(triShape, node, composite, boundTextures, animflags);
if (!nifNode->controller.empty())
handleMeshControllers(nifNode, composite, boundTextures, animflags);
handleMeshControllers(nifNode, node, composite, boundTextures, animflags);
}
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
@ -570,7 +571,7 @@ namespace NifOsg
return node;
}
void handleMeshControllers(const Nif::Node *nifNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int> &boundTextures, int animflags)
void handleMeshControllers(const Nif::Node *nifNode, osg::Node* node, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int> &boundTextures, int animflags)
{
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
{
@ -587,6 +588,14 @@ namespace NifOsg
setupController(uvctrl, ctrl, animflags);
composite->addController(ctrl);
}
else if (ctrl->recType == Nif::RC_NiVisController)
{
handleVisController(static_cast<const Nif::NiVisController*>(ctrl.getPtr()), node, animflags);
}
else if(ctrl->recType == Nif::RC_NiGeomMorpherController)
{} // handled in handleTriShape
else
std::cerr << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename << std::endl;
}
}
@ -609,15 +618,20 @@ namespace NifOsg
}
else if (ctrl->recType == Nif::RC_NiVisController)
{
const Nif::NiVisController* visctrl = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
osg::ref_ptr<VisController> callback(new VisController(visctrl->data.getPtr()));
setupController(visctrl, callback, animflags);
transformNode->addUpdateCallback(callback);
handleVisController(static_cast<const Nif::NiVisController*>(ctrl.getPtr()), transformNode, animflags);
}
else
std::cerr << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename << std::endl;
}
}
void handleVisController(const Nif::NiVisController* visctrl, osg::Node* node, int animflags)
{
osg::ref_ptr<VisController> callback(new VisController(visctrl->data.getPtr()));
setupController(visctrl, callback, animflags);
node->addUpdateCallback(callback);
}
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
{
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
@ -810,6 +824,8 @@ namespace NifOsg
continue;
if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController)
partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr());
else
std::cerr << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename << std::endl;
}
if (!partctrl)
{
@ -870,9 +886,6 @@ namespace NifOsg
// localToWorldMatrix for transforming to particle space
handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf);
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(partsys);
std::vector<const Nif::Property*> drawableProps;
collectDrawableProperties(nifNode, drawableProps);
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
@ -892,13 +905,21 @@ namespace NifOsg
updater->addParticleSystem(partsys);
parentNode->addChild(updater);
#if OSG_VERSION_LESS_THAN(3,3,3)
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(partsys);
osg::Node* toAttach = geode.get();
#else
osg::Node* toAttach = partsys.get();
#endif
if (rf == osgParticle::ParticleProcessor::RELATIVE_RF)
parentNode->addChild(geode);
parentNode->addChild(toAttach);
else
{
osg::MatrixTransform* trans = new osg::MatrixTransform;
trans->setUpdateCallback(new InverseWorldMatrix);
trans->addChild(geode);
trans->addChild(toAttach);
parentNode->addChild(trans);
}
}
@ -943,44 +964,57 @@ namespace NifOsg
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
{
osg::ref_ptr<osg::Geometry> geometry;
if(!triShape->controller.empty())
for (Nif::ControllerPtr ctrl = triShape->controller; !ctrl.empty(); ctrl = ctrl->next)
{
Nif::ControllerPtr ctrl = triShape->controller;
do {
if(ctrl->recType == Nif::RC_NiGeomMorpherController && ctrl->flags & Nif::NiNode::ControllerFlag_Active)
{
geometry = handleMorphGeometry(static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr()));
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
continue;
if(ctrl->recType == Nif::RC_NiGeomMorpherController)
{
geometry = handleMorphGeometry(static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr()));
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());
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;
}
}
if (!geometry.get())
geometry = new osg::Geometry;
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
#if OSG_VERSION_LESS_THAN(3,3,3)
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(geometry);
#endif
if (geometry->getDataVariance() == osg::Object::DYNAMIC)
{
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
geometry->setDataVariance(osg::Object::STATIC);
osg::ref_ptr<osg::Geode> geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
#if OSG_VERSION_LESS_THAN(3,3,3)
osg::ref_ptr<osg::Geode> geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
frameswitch->addChild(geode);
frameswitch->addChild(geode2);
#else
osg::ref_ptr<osg::Geometry> geom2 = static_cast<osg::Geometry*>(osg::clone(geometry.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
frameswitch->addChild(geometry);
frameswitch->addChild(geom2);
#endif
parentNode->addChild(frameswitch);
}
else
#if OSG_VERSION_LESS_THAN(3,3,3)
parentNode->addChild(geode);
#else
parentNode->addChild(geometry);
#endif
}
osg::ref_ptr<osg::Geometry> handleMorphGeometry(const Nif::NiGeomMorpherController* morpher)
@ -1041,8 +1075,6 @@ namespace NifOsg
void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
const std::vector<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, parentNode, composite, boundTextures, animflags);
@ -1075,17 +1107,27 @@ namespace NifOsg
}
rig->setInfluenceMap(map);
geode->addDrawable(rig);
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
rig->setDataVariance(osg::Object::STATIC);
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
#if OSG_VERSION_LESS_THAN(3,3,3)
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable(rig);
osg::Geode* geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|
osg::CopyOp::DEEP_COPY_DRAWABLES));
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
frameswitch->addChild(geode);
frameswitch->addChild(geode2);
#else
SceneUtil::RigGeometry* rig2 = static_cast<SceneUtil::RigGeometry*>(osg::clone(rig.get(), osg::CopyOp::DEEP_COPY_NODES|
osg::CopyOp::DEEP_COPY_DRAWABLES));
frameswitch->addChild(rig);
frameswitch->addChild(rig2);
#endif
parentNode->addChild(frameswitch);
}
@ -1365,7 +1407,7 @@ namespace NifOsg
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;
osg::ref_ptr<osg::Material> mat (new osg::Material);
mat->setColorMode(hasVertexColors ? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF);
// NIF material defaults don't match OpenGL defaults
@ -1420,12 +1462,11 @@ namespace NifOsg
case Nif::RC_NiAlphaProperty:
{
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property);
osg::BlendFunc* blendfunc = new osg::BlendFunc;
if (alphaprop->flags&1)
{
blendfunc->setFunction(getBlendMode((alphaprop->flags>>1)&0xf),
getBlendMode((alphaprop->flags>>5)&0xf));
stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON);
stateset->setAttributeAndModes(new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf),
getBlendMode((alphaprop->flags>>5)&0xf)),
osg::StateAttribute::ON);
bool noSort = (alphaprop->flags>>13)&1;
if (!noSort)
@ -1440,11 +1481,10 @@ namespace NifOsg
stateset->setRenderBinToInherit();
}
osg::AlphaFunc* alphafunc = new osg::AlphaFunc;
if((alphaprop->flags>>9)&1)
{
alphafunc->setFunction(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f);
stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::ON);
stateset->setAttributeAndModes(new osg::AlphaFunc(getTestMode((alphaprop->flags>>10)&0x7),
alphaprop->data.threshold/255.f), osg::StateAttribute::ON);
}
else
{

@ -60,7 +60,7 @@ namespace NifOsg
InverseWorldMatrix()
{
}
InverseWorldMatrix(const InverseWorldMatrix& copy, const osg::CopyOp& op = osg::CopyOp::SHALLOW_COPY)
InverseWorldMatrix(const InverseWorldMatrix& copy, const osg::CopyOp& op)
: osg::Object(), osg::NodeCallback()
{
}
@ -139,9 +139,6 @@ namespace NifOsg
META_Object(NifOsg, ParticleColorAffector)
// TODO: very similar to vec3 version, refactor to a template
osg::Vec4f interpolate(const float time, const Nif::Vector4KeyMap::MapType& keys);
virtual void operate(osgParticle::Particle* particle, double dt);
private:

@ -3,6 +3,7 @@
#include <osg/Node>
#include <osg/Geode>
#include <osg/UserDataContainer>
#include <osg/Version>
#include <osgParticle/ParticleSystem>
@ -25,35 +26,54 @@ namespace
class InitWorldSpaceParticlesVisitor : public osg::NodeVisitor
{
public:
InitWorldSpaceParticlesVisitor()
/// @param mask The node mask to set on ParticleSystem nodes.
InitWorldSpaceParticlesVisitor(unsigned int mask)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mMask(mask)
{
}
void apply(osg::Node& node)
bool isWorldSpaceParticleSystem(osgParticle::ParticleSystem* partsys)
{
if (osg::Geode* geode = node.asGeode())
// HACK: ParticleSystem has no getReferenceFrame()
return (partsys->getUserDataContainer()
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace");
}
void apply(osg::Geode& geode)
{
for (unsigned int i=0;i<geode.getNumDrawables();++i)
{
for (unsigned int i=0;i<geode->getNumDrawables();++i)
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(geode.getDrawable(i)))
{
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(geode->getDrawable(i)))
if (isWorldSpaceParticleSystem(partsys))
{
// HACK: ParticleSystem has no getReferenceFrame()
if (partsys->getUserDataContainer()
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace")
{
// HACK: Ignore the InverseWorldMatrix transform the geode is attached to
if (geode->getNumParents() && geode->getParent(0)->getNumParents())
transformInitialParticles(partsys, geode->getParent(0)->getParent(0));
}
geode->setNodeMask((1<<10)); //MWRender::Mask_ParticleSystem
// HACK: Ignore the InverseWorldMatrix transform the geode is attached to
if (geode.getNumParents() && geode.getParent(0)->getNumParents())
transformInitialParticles(partsys, geode.getParent(0)->getParent(0));
}
geode.setNodeMask(mMask);
}
}
}
traverse(node);
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
// in OSG 3.3 and up Drawables can be directly in the scene graph without a Geode decorating them.
void apply(osg::Drawable& drw)
{
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
{
if (isWorldSpaceParticleSystem(partsys))
{
// HACK: Ignore the InverseWorldMatrix transform the particle system is attached to
if (partsys->getNumParents() && partsys->getParent(0)->getNumParents())
transformInitialParticles(partsys, partsys->getParent(0)->getParent(0));
}
partsys->setNodeMask(mMask);
}
}
#endif
void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node)
{
@ -74,8 +94,9 @@ namespace
box.expandBy(sphere);
partsys->setInitialBound(box);
}
private:
unsigned int mMask;
};
}
namespace Resource
@ -84,6 +105,7 @@ namespace Resource
SceneManager::SceneManager(const VFS::Manager *vfs, Resource::TextureManager* textureManager)
: mVFS(vfs)
, mTextureManager(textureManager)
, mParticleSystemMask(~0u)
{
}
@ -183,7 +205,7 @@ namespace Resource
void SceneManager::notifyAttached(osg::Node *node) const
{
InitWorldSpaceParticlesVisitor visitor;
InitWorldSpaceParticlesVisitor visitor (mParticleSystemMask);
node->accept(visitor);
}
@ -197,4 +219,9 @@ namespace Resource
return mTextureManager;
}
void SceneManager::setParticleSystemMask(unsigned int mask)
{
mParticleSystemMask = mask;
}
}

@ -73,12 +73,17 @@ namespace Resource
Resource::TextureManager* getTextureManager();
/// @param mask The node mask to apply to loaded particle system nodes.
void setParticleSystemMask(unsigned int mask);
private:
const VFS::Manager* mVFS;
Resource::TextureManager* mTextureManager;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
unsigned int mParticleSystemMask;
// observer_ptr?
typedef std::map<std::string, osg::ref_ptr<const osg::Node> > Index;
Index mIndex;

@ -119,7 +119,7 @@ namespace Resource
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
{
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
osg::GLExtensions* exts = osg::GLExtensions::Get(0, false);
if (exts && !exts->isTextureCompressionS3TCSupported
// This one works too. Should it be included in isTextureCompressionS3TCSupported()? Submitted as a patch to OSG.

@ -65,7 +65,7 @@ namespace SceneUtil
void ControllerVisitor::apply(osg::Node &node)
{
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
osg::Callback* callback = node.getUpdateCallback();
#else
osg::NodeCallback* callback = node.getUpdateCallback();
@ -96,7 +96,7 @@ namespace SceneUtil
{
osg::Drawable* drw = geode.getDrawable(i);
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
osg::Callback* callback = drw->getUpdateCallback();
#else
osg::Drawable::UpdateCallback* callback = drw->getUpdateCallback();

@ -131,6 +131,7 @@ namespace SceneUtil
LightManager::LightManager()
: mStartLight(0)
, mLightingMask(~0u)
{
setUpdateCallback(new LightManagerUpdateCallback);
}
@ -138,10 +139,21 @@ namespace SceneUtil
LightManager::LightManager(const LightManager &copy, const osg::CopyOp &copyop)
: osg::Group(copy, copyop)
, mStartLight(copy.mStartLight)
, mLightingMask(copy.mLightingMask)
{
}
void LightManager::setLightingMask(unsigned int mask)
{
mLightingMask = mask;
}
unsigned int LightManager::getLightingMask() const
{
return mLightingMask;
}
void LightManager::update()
{
mLights.clear();
@ -237,7 +249,6 @@ namespace SceneUtil
LightSource::LightSource()
: mRadius(0.f)
{
setNodeMask(Mask_Lit);
setUpdateCallback(new CollectLightCallback);
mId = sLightId++;
}
@ -260,12 +271,6 @@ namespace SceneUtil
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
if (!(cv->getCurrentCamera()->getCullMask()&Mask_Lit))
{
traverse(node, nv);
return;
}
if (!mLightManager)
{
mLightManager = findLightManager(nv->getNodePath());
@ -276,6 +281,12 @@ namespace SceneUtil
}
}
if (!(cv->getCurrentCamera()->getCullMask() & mLightManager->getLightingMask()))
{
traverse(node, nv);
return;
}
// Possible optimizations:
// - cull list of lights by the camera frustum
// - organize lights in a quad tree

@ -9,9 +9,6 @@
namespace SceneUtil
{
// This mask should be included in the Cull and Update visitor's traversal mask if lighting is desired.
const int Mask_Lit = (1<<16);
/// LightSource managed by a LightManager.
class LightSource : public osg::Node
{
@ -68,6 +65,14 @@ namespace SceneUtil
LightManager(const LightManager& copy, const osg::CopyOp& copyop);
/// @param mask This mask is compared with the current Camera's cull mask to determine if lighting is desired.
/// By default, it's ~0u i.e. always on.
/// If you have some views that do not require lighting, then set the Camera's cull mask to not include
/// the lightingMask for a much faster cull and rendering.
void setLightingMask (unsigned int mask);
unsigned int getLightingMask() const;
// Called automatically by the UpdateCallback
void update();
@ -111,6 +116,8 @@ namespace SceneUtil
LightStateSetMap mStateSetCache;
int mStartLight;
unsigned int mLightingMask;
};
/// @note Not thread safe for CullThreadPerCamera threading mode.
@ -121,7 +128,7 @@ namespace SceneUtil
: mLightManager(NULL)
, mLastFrameNumber(0)
{}
LightListCallback(const LightListCallback& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY)
LightListCallback(const LightListCallback& copy, const osg::CopyOp& copyop)
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop)
, mLightManager(copy.mLightManager)
, mLastFrameNumber(0)

@ -2,9 +2,9 @@
#include <stdexcept>
#include <iostream>
#include <cstdlib>
#include <osg/Version>
#include <osg/MatrixTransform>
#include "skeleton.hpp"
@ -58,6 +58,14 @@ public:
}
};
// We can't compute the bounds without a NodeVisitor, since we need the current geomToSkelMatrix.
// So we return nothing. Bounds are updated every frame in the UpdateCallback.
class DummyComputeBoundCallback : public osg::Drawable::ComputeBoundingBoxCallback
{
public:
virtual osg::BoundingBox computeBound(const osg::Drawable&) const { return osg::BoundingBox(); }
};
RigGeometry::RigGeometry()
: mSkeleton(NULL)
, mLastFrameNumber(0)
@ -66,6 +74,7 @@ RigGeometry::RigGeometry()
setCullCallback(new UpdateRigGeometry);
setUpdateCallback(new UpdateRigBounds);
setSupportsDisplayList(false);
setComputeBoundingBoxCallback(new DummyComputeBoundCallback);
}
RigGeometry::RigGeometry(const RigGeometry &copy, const osg::CopyOp &copyop)
@ -278,6 +287,12 @@ void RigGeometry::updateBounds(osg::NodeVisitor *nv)
}
_boundingBox = box;
_boundingBoxComputed = true;
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
// in OSG 3.3.3 and up Drawable inherits from Node, so has a bounding sphere as well.
_boundingSphere = osg::BoundingSphere(_boundingBox);
_boundingSphereComputed = true;
#endif
for (unsigned int i=0; i<getNumParents(); ++i)
getParent(i)->dirtyBound();
}

@ -22,11 +22,13 @@ namespace SceneUtil
void DisableFreezeOnCullVisitor::apply(osg::Geode &geode)
{
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
{
osg::Drawable* drw = geode.getDrawable(i);
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(drw))
partsys->setFreezeOnCull(false);
}
apply(*geode.getDrawable(i));
}
void DisableFreezeOnCullVisitor::apply(osg::Drawable& drw)
{
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
partsys->setFreezeOnCull(false);
}
}

@ -35,6 +35,7 @@ namespace SceneUtil
}
virtual void apply(osg::Geode &geode);
virtual void apply(osg::Drawable& drw);
};
}

@ -2,7 +2,6 @@
#include <SDL_video.h>
#include <osg/DeleteHandler>
#include <osg/Version>
namespace SDLUtil
@ -79,15 +78,13 @@ void GraphicsWindowSDL2::init()
if(!_traits.valid())
return;
// getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
WindowData *inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
mWindow = inheritedWindowData ? inheritedWindowData->mWindow : NULL;
mOwnsWindow = (mWindow == 0);
if(mOwnsWindow)
{
OSG_NOTICE<<"Error: No SDL window provided."<<std::endl;
OSG_FATAL<<"Error: No SDL window provided."<<std::endl;
return;
}
@ -99,7 +96,7 @@ void GraphicsWindowSDL2::init()
mContext = SDL_GL_CreateContext(mWindow);
if(!mContext)
{
OSG_NOTICE<< "Error: Unable to create OpenGL graphics context: "<<SDL_GetError() <<std::endl;
OSG_FATAL<< "Error: Unable to create OpenGL graphics context: "<<SDL_GetError() <<std::endl;
return;
}
@ -109,7 +106,7 @@ void GraphicsWindowSDL2::init()
mValid = true;
#if OSG_MIN_VERSION_REQUIRED(3,3,4)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,4)
getEventQueue()->syncWindowRectangleWithGraphicsContext();
#else
getEventQueue()->syncWindowRectangleWithGraphcisContext();
@ -130,7 +127,7 @@ bool GraphicsWindowSDL2::realizeImplementation()
SDL_ShowWindow(mWindow);
#if OSG_MIN_VERSION_REQUIRED(3,3,4)
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,4)
getEventQueue()->syncWindowRectangleWithGraphicsContext();
#else
getEventQueue()->syncWindowRectangleWithGraphcisContext();
@ -145,7 +142,7 @@ bool GraphicsWindowSDL2::makeCurrentImplementation()
{
if(!mRealized)
{
OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
OSG_WARN<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
return false;
}
@ -156,7 +153,7 @@ bool GraphicsWindowSDL2::releaseContextImplementation()
{
if(!mRealized)
{
OSG_NOTICE<< "Warning: GraphicsWindow not realized, cannot do releaseContext." <<std::endl;
OSG_WARN<< "Warning: GraphicsWindow not realized, cannot do releaseContext." <<std::endl;
return false;
}
@ -166,8 +163,6 @@ bool GraphicsWindowSDL2::releaseContextImplementation()
void GraphicsWindowSDL2::closeImplementation()
{
// OSG_NOTICE<<"Closing GraphicsWindowSDL2"<<std::endl;
if(mContext)
SDL_GL_DeleteContext(mContext);
mContext = NULL;
@ -184,8 +179,6 @@ void GraphicsWindowSDL2::swapBuffersImplementation()
{
if(!mRealized) return;
//OSG_NOTICE<< "swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
SDL_GL_SwapWindow(mWindow);
}

Loading…
Cancel
Save