mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:19:55 +00:00
Merge remote-tracking branch 'scrawl/master' into openmw-37
This commit is contained in:
commit
77b325a1db
33 changed files with 397 additions and 220 deletions
2
.gitignore
vendored
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();
|
||||
|
||||
if(mDistSameSpot == -1)
|
||||
mDistSameSpot = DIST_SAME_SPOT * (cls.getSpeed(actor) / 150);
|
||||
// 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// Removes all drawables from a graph.
|
||||
class RemoveDrawableVisitor : public osg::NodeVisitor
|
||||
/// @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:
|
||||
RemoveDrawableVisitor()
|
||||
RemoveVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply(osg::Geode &node)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
{
|
||||
osg::Node* node = *it;
|
||||
if (node->getNumParents())
|
||||
node->getParent(0)->removeChild(node);
|
||||
}
|
||||
for (RemoveVec::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
it->second->removeChild(it->first);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<osg::Node*> mToRemove;
|
||||
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;
|
||||
};
|
||||
|
||||
class RemoveTriBipVisitor : public osg::NodeVisitor
|
||||
// Removes all drawables from a graph.
|
||||
class RemoveDrawableVisitor : public RemoveVisitor
|
||||
{
|
||||
public:
|
||||
RemoveTriBipVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
virtual void apply(osg::Geode &geode)
|
||||
{
|
||||
applyImpl(geode);
|
||||
}
|
||||
|
||||
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||
virtual void apply(osg::Drawable& drw)
|
||||
{
|
||||
applyImpl(drw);
|
||||
}
|
||||
#endif
|
||||
|
||||
void applyImpl(osg::Node& node)
|
||||
{
|
||||
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())
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
mToRemove.push_back(std::make_pair(&node, parentGroup));
|
||||
}
|
||||
};
|
||||
|
||||
class RemoveTriBipVisitor : public RemoveVisitor
|
||||
{
|
||||
public:
|
||||
virtual void apply(osg::Geode &node)
|
||||
{
|
||||
applyImpl(node);
|
||||
}
|
||||
|
||||
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||
virtual void apply(osg::Drawable& drw)
|
||||
{
|
||||
applyImpl(drw);
|
||||
}
|
||||
#endif
|
||||
|
||||
void applyImpl(osg::Node& node)
|
||||
{
|
||||
const std::string toFind = "tri bip";
|
||||
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
|
||||
{
|
||||
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(&node);
|
||||
mToRemove.push_back(std::make_pair(&node, parent));
|
||||
}
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
{
|
||||
osg::Node* node = *it;
|
||||
if (node->getNumParents())
|
||||
node->getParent(0)->removeChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
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,36 +26,55 @@ 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)
|
||||
{
|
||||
osg::MatrixList mats = node->getWorldMatrices();
|
||||
|
@ -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 ©, const osg::CopyOp ©op)
|
||||
: 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 ©, const osg::CopyOp ©op)
|
||||
|
@ -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…
Reference in a new issue