Clean up NIF flags

just_say_no_to_geode
Alexei Kotov 3 years ago
parent 1a478875f0
commit e673f9fa76

@ -484,7 +484,7 @@ namespace
TEST_F(TestBulletNifLoader, for_root_nif_node_with_bounding_box_should_return_shape_with_compound_shape_and_box_inside) TEST_F(TestBulletNifLoader, for_root_nif_node_with_bounding_box_should_return_shape_with_compound_shape_and_box_inside)
{ {
mNode.hasBounds = true; mNode.hasBounds = true;
mNode.flags |= Nif::NiNode::Flag_BBoxCollision; mNode.flags |= Nif::Node::Flag_BBoxCollision;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
@ -508,7 +508,7 @@ namespace
TEST_F(TestBulletNifLoader, for_child_nif_node_with_bounding_box) TEST_F(TestBulletNifLoader, for_child_nif_node_with_bounding_box)
{ {
mNode.hasBounds = true; mNode.hasBounds = true;
mNode.flags |= Nif::NiNode::Flag_BBoxCollision; mNode.flags |= Nif::Node::Flag_BBoxCollision;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
@ -534,7 +534,7 @@ namespace
TEST_F(TestBulletNifLoader, for_root_and_child_nif_node_with_bounding_box_but_root_without_flag_should_use_child_bounds) TEST_F(TestBulletNifLoader, for_root_and_child_nif_node_with_bounding_box_but_root_without_flag_should_use_child_bounds)
{ {
mNode.hasBounds = true; mNode.hasBounds = true;
mNode.flags |= Nif::NiNode::Flag_BBoxCollision; mNode.flags |= Nif::Node::Flag_BBoxCollision;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
@ -565,7 +565,7 @@ namespace
TEST_F(TestBulletNifLoader, for_root_and_two_children_where_both_with_bounds_but_only_first_with_flag_should_use_first_bounds) TEST_F(TestBulletNifLoader, for_root_and_two_children_where_both_with_bounds_but_only_first_with_flag_should_use_first_bounds)
{ {
mNode.hasBounds = true; mNode.hasBounds = true;
mNode.flags |= Nif::NiNode::Flag_BBoxCollision; mNode.flags |= Nif::Node::Flag_BBoxCollision;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
@ -608,7 +608,7 @@ namespace
mNode.parents.push_back(&mNiNode); mNode.parents.push_back(&mNiNode);
mNode2.hasBounds = true; mNode2.hasBounds = true;
mNode2.flags |= Nif::NiNode::Flag_BBoxCollision; mNode2.flags |= Nif::Node::Flag_BBoxCollision;
mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6); mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6);
mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6); mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6);
@ -861,7 +861,7 @@ namespace
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_controller_should_return_shape_with_compound_shape) TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_controller_should_return_shape_with_compound_shape)
{ {
mController.recType = Nif::RC_NiKeyframeController; mController.recType = Nif::RC_NiKeyframeController;
mController.flags |= Nif::NiNode::ControllerFlag_Active; mController.flags |= Nif::Controller::Flag_Active;
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.trafo);
mNiTriShape.trafo.scale = 3; mNiTriShape.trafo.scale = 3;
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
@ -890,7 +890,7 @@ namespace
TEST_F(TestBulletNifLoader, for_two_tri_shape_children_nodes_where_one_with_controller_should_return_shape_with_compound_shape) TEST_F(TestBulletNifLoader, for_two_tri_shape_children_nodes_where_one_with_controller_should_return_shape_with_compound_shape)
{ {
mController.recType = Nif::RC_NiKeyframeController; mController.recType = Nif::RC_NiKeyframeController;
mController.flags |= Nif::NiNode::ControllerFlag_Active; mController.flags |= Nif::Controller::Flag_Active;
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.trafo);
mNiTriShape.trafo.scale = 3; mNiTriShape.trafo.scale = 3;
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);

@ -33,6 +33,18 @@ struct Extra : public Record
struct Controller : public Record struct Controller : public Record
{ {
enum Flags {
Flag_Active = 0x8
};
enum ExtrapolationMode
{
Cycle = 0,
Reverse = 2,
Constant = 4,
Mask = 6
};
ControllerPtr next; ControllerPtr next;
int flags; int flags;
float frequency, phase; float frequency, phase;
@ -41,6 +53,9 @@ struct Controller : public Record
void read(NIFStream *nif) override; void read(NIFStream *nif) override;
void post(NIFFile *nif) override; void post(NIFFile *nif) override;
bool isActive() const { return flags & Flag_Active; }
ExtrapolationMode extrapolationMode() const { return static_cast<ExtrapolationMode>(flags & Mask); }
}; };
/// Has name, extra-data and controller /// Has name, extra-data and controller

@ -31,6 +31,11 @@ namespace Nif
struct NiParticleSystemController : public Controller struct NiParticleSystemController : public Controller
{ {
enum BSPArrayController {
BSPArrayController_AtNode = 0x8,
BSPArrayController_AtVertex = 0x10
};
struct Particle { struct Particle {
osg::Vec3f velocity; osg::Vec3f velocity;
float lifetime; float lifetime;
@ -57,7 +62,7 @@ struct NiParticleSystemController : public Controller
enum EmitFlags enum EmitFlags
{ {
NoAutoAdjust = 0x1 // If this flag is set, we use the emitRate value. Otherwise, EmitFlag_NoAutoAdjust = 0x1 // If this flag is set, we use the emitRate value. Otherwise,
// we calculate an emit rate so that the maximum number of particles // we calculate an emit rate so that the maximum number of particles
// in the system (numParticles) is never exceeded. // in the system (numParticles) is never exceeded.
}; };
@ -76,6 +81,9 @@ struct NiParticleSystemController : public Controller
void read(NIFStream *nif) override; void read(NIFStream *nif) override;
void post(NIFFile *nif) override; void post(NIFFile *nif) override;
bool noAutoAdjust() const { return flags & EmitFlag_NoAutoAdjust; }
bool emitAtVertex() const { return flags & BSPArrayController_AtVertex; }
}; };
using NiBSPArrayController = NiParticleSystemController; using NiBSPArrayController = NiParticleSystemController;

@ -96,6 +96,9 @@ struct NiTextureEffect : NiDynamicEffect
void read(NIFStream *nif) override; void read(NIFStream *nif) override;
void post(NIFFile *nif) override; void post(NIFFile *nif) override;
bool wrapT() const { return clamp & 1; }
bool wrapS() const { return (clamp >> 1) & 1; }
}; };
} // Namespace } // Namespace

@ -144,8 +144,16 @@ struct NiBoundingVolume
*/ */
struct Node : public Named struct Node : public Named
{ {
enum Flags {
Flag_Hidden = 0x0001,
Flag_MeshCollision = 0x0002,
Flag_BBoxCollision = 0x0004,
Flag_ActiveCollision = 0x0020
};
// Node flags. Interpretation depends somewhat on the type of node. // Node flags. Interpretation depends somewhat on the type of node.
unsigned int flags; unsigned int flags;
Transformation trafo; Transformation trafo;
osg::Vec3f velocity; // Unused? Might be a run-time game state osg::Vec3f velocity; // Unused? Might be a run-time game state
PropertyList props; PropertyList props;
@ -198,6 +206,11 @@ struct Node : public Named
{ {
isBone = true; isBone = true;
} }
bool isHidden() const { return flags & Flag_Hidden; }
bool hasMeshCollision() const { return flags & Flag_MeshCollision; }
bool hasBBoxCollision() const { return flags & Flag_BBoxCollision; }
bool collisionActive() const { return flags & Flag_ActiveCollision; }
}; };
struct NiNode : Node struct NiNode : Node
@ -205,12 +218,6 @@ struct NiNode : Node
NodeList children; NodeList children;
NodeList effects; NodeList effects;
enum Flags {
Flag_Hidden = 0x0001,
Flag_MeshCollision = 0x0002,
Flag_BBoxCollision = 0x0004,
Flag_ActiveCollision = 0x0020
};
enum BSAnimFlags { enum BSAnimFlags {
AnimFlag_AutoPlay = 0x0020 AnimFlag_AutoPlay = 0x0020
}; };
@ -218,13 +225,6 @@ struct NiNode : Node
ParticleFlag_AutoPlay = 0x0020, ParticleFlag_AutoPlay = 0x0020,
ParticleFlag_LocalSpace = 0x0080 ParticleFlag_LocalSpace = 0x0080
}; };
enum ControllerFlags {
ControllerFlag_Active = 0x8
};
enum BSPArrayController {
BSPArrayController_AtNode = 0x8,
BSPArrayController_AtVertex = 0x10
};
void read(NIFStream *nif) override void read(NIFStream *nif) override
{ {
@ -450,12 +450,13 @@ struct NiFltAnimationNode : public NiSwitchNode
Flag_Swing = 0x40 Flag_Swing = 0x40
}; };
void read(NIFStream *nif) override void read(NIFStream *nif) override
{ {
NiSwitchNode::read(nif); NiSwitchNode::read(nif);
mDuration = nif->getFloat(); mDuration = nif->getFloat();
} }
bool swing() const { return flags & Flag_Swing; }
}; };
// Abstract // Abstract

@ -52,6 +52,9 @@ struct NiTexturingProperty : public Property
void read(NIFStream *nif); void read(NIFStream *nif);
void post(NIFFile *nif); void post(NIFFile *nif);
bool wrapT() const { return clamp & 1; }
bool wrapS() const { return (clamp >> 1) & 1; }
}; };
/* Apply mode: /* Apply mode:
@ -140,6 +143,9 @@ struct BSShaderLightingProperty : public BSShaderProperty
{ {
unsigned int clamp{0u}; unsigned int clamp{0u};
void read(NIFStream *nif) override; void read(NIFStream *nif) override;
bool wrapT() const { return clamp & 1; }
bool wrapS() const { return (clamp >> 1) & 1; }
}; };
struct BSShaderPPLightingProperty : public BSShaderLightingProperty struct BSShaderPPLightingProperty : public BSShaderLightingProperty
@ -230,6 +236,10 @@ struct NiZBufferProperty : public Property
if (nif->getVersion() >= NIFStream::generateVersion(4,1,0,12) && nif->getVersion() <= NIFFile::NIFVersion::VER_OB) if (nif->getVersion() >= NIFStream::generateVersion(4,1,0,12) && nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
testFunction = nif->getUInt(); testFunction = nif->getUInt();
} }
bool depthTest() const { return flags & 1; }
bool depthWrite() const { return (flags >> 1) & 1; }
}; };
struct NiSpecularProperty : public Property struct NiSpecularProperty : public Property
@ -240,6 +250,8 @@ struct NiSpecularProperty : public Property
Property::read(nif); Property::read(nif);
flags = nif->getUShort(); flags = nif->getUShort();
} }
bool isEnabled() const { return flags & 1; }
}; };
struct NiWireframeProperty : public Property struct NiWireframeProperty : public Property
@ -250,6 +262,8 @@ struct NiWireframeProperty : public Property
Property::read(nif); Property::read(nif);
flags = nif->getUShort(); flags = nif->getUShort();
} }
bool isEnabled() const { return flags & 1; }
}; };
// The rest are all struct-based // The rest are all struct-based
@ -296,16 +310,7 @@ struct S_VertexColorProperty
struct S_AlphaProperty struct S_AlphaProperty
{ {
/* /*
In NiAlphaProperty, the flags have the following meaning: NiAlphaProperty blend modes (glBlendFunc):
Bit 0 : alpha blending enable
Bits 1-4 : source blend mode
Bits 5-8 : destination blend mode
Bit 9 : alpha test enable
Bit 10-12 : alpha test mode
Bit 13 : no sorter flag ( disables triangle sorting )
blend modes (glBlendFunc):
0000 GL_ONE 0000 GL_ONE
0001 GL_ZERO 0001 GL_ZERO
0010 GL_SRC_COLOR 0010 GL_SRC_COLOR
@ -384,7 +389,17 @@ struct S_StencilProperty
void read(NIFStream *nif); void read(NIFStream *nif);
}; };
struct NiAlphaProperty : public StructPropT<S_AlphaProperty> { }; struct NiAlphaProperty : public StructPropT<S_AlphaProperty>
{
bool useAlphaBlending() const { return flags & 1; }
int sourceBlendMode() const { return (flags >> 1) & 0xF; }
int destinationBlendMode() const { return (flags >> 5) & 0xF; }
bool noSorter() const { return (flags >> 13) & 1; }
bool useAlphaTesting() const { return (flags >> 9) & 1; }
int alphaTestMode() const { return (flags >> 10) & 0x7; }
};
struct NiVertexColorProperty : public StructPropT<S_VertexColorProperty> { }; struct NiVertexColorProperty : public StructPropT<S_VertexColorProperty> { };
struct NiStencilProperty : public Property struct NiStencilProperty : public Property
{ {

@ -270,7 +270,7 @@ bool BulletNifLoader::findBoundingBox(const Nif::Node& node, const std::string&
} }
} }
if (node.flags & Nif::NiNode::Flag_BBoxCollision) if (node.hasBBoxCollision())
{ {
return true; return true;
} }
@ -312,15 +312,14 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& n
int flags, bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid, unsigned int& collisionType) int flags, bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid, unsigned int& collisionType)
{ {
// TODO: allow on-the fly collision switching via toggling this flag // TODO: allow on-the fly collision switching via toggling this flag
if (node.recType == Nif::RC_NiCollisionSwitch && !(node.flags & Nif::NiNode::Flag_ActiveCollision)) if (node.recType == Nif::RC_NiCollisionSwitch && !node.collisionActive())
return; return;
// Accumulate the flags from all the child nodes. This works for all // Accumulate the flags from all the child nodes. This works for all
// the flags we currently use, at least. // the flags we currently use, at least.
flags |= node.flags; flags |= node.flags;
if (!node.controller.empty() && node.controller->recType == Nif::RC_NiKeyframeController if (!node.controller.empty() && node.controller->recType == Nif::RC_NiKeyframeController && node.controller->isActive())
&& (node.controller->flags & Nif::NiNode::ControllerFlag_Active))
isAnimated = true; isAnimated = true;
isCollisionNode = isCollisionNode || (node.recType == Nif::RC_RootCollisionNode); isCollisionNode = isCollisionNode || (node.recType == Nif::RC_RootCollisionNode);

@ -20,7 +20,7 @@ ControllerFunction::ControllerFunction(const Nif::Controller *ctrl)
, mPhase(ctrl->phase) , mPhase(ctrl->phase)
, mStartTime(ctrl->timeStart) , mStartTime(ctrl->timeStart)
, mStopTime(ctrl->timeStop) , mStopTime(ctrl->timeStop)
, mExtrapolationMode(static_cast<ExtrapolationMode>((ctrl->flags&0x6) >> 1)) , mExtrapolationMode(ctrl->extrapolationMode())
{ {
} }
@ -31,7 +31,7 @@ float ControllerFunction::calculate(float value) const
return time; return time;
switch (mExtrapolationMode) switch (mExtrapolationMode)
{ {
case Cycle: case Nif::Controller::ExtrapolationMode::Cycle:
{ {
float delta = mStopTime - mStartTime; float delta = mStopTime - mStartTime;
if ( delta <= 0 ) if ( delta <= 0 )
@ -40,7 +40,7 @@ float ControllerFunction::calculate(float value) const
float remainder = ( cycles - std::floor( cycles ) ) * delta; float remainder = ( cycles - std::floor( cycles ) ) * delta;
return mStartTime + remainder; return mStartTime + remainder;
} }
case Reverse: case Nif::Controller::ExtrapolationMode::Reverse:
{ {
float delta = mStopTime - mStartTime; float delta = mStopTime - mStartTime;
if ( delta <= 0 ) if ( delta <= 0 )
@ -55,7 +55,7 @@ float ControllerFunction::calculate(float value) const
return mStopTime - remainder; return mStopTime - remainder;
} }
case Constant: case Nif::Controller::ExtrapolationMode::Constant:
default: default:
return std::clamp(time, mStartTime, mStopTime); return std::clamp(time, mStartTime, mStopTime);
} }

@ -200,13 +200,7 @@ namespace NifOsg
float mPhase; float mPhase;
float mStartTime; float mStartTime;
float mStopTime; float mStopTime;
enum ExtrapolationMode Nif::Controller::ExtrapolationMode mExtrapolationMode;
{
Cycle = 0,
Reverse = 1,
Constant = 2
};
ExtrapolationMode mExtrapolationMode;
public: public:
ControllerFunction(const Nif::Controller *ctrl); ControllerFunction(const Nif::Controller *ctrl);

@ -439,7 +439,7 @@ namespace NifOsg
sequenceNode->setName(niFltAnimationNode->name); sequenceNode->setName(niFltAnimationNode->name);
if (niFltAnimationNode->children.length()!=0) if (niFltAnimationNode->children.length()!=0)
{ {
if (niFltAnimationNode->flags & Nif::NiFltAnimationNode::Flag_Swing) if (niFltAnimationNode->swing())
sequenceNode->setDefaultTime(niFltAnimationNode->mDuration/(niFltAnimationNode->children.length()*2)); sequenceNode->setDefaultTime(niFltAnimationNode->mDuration/(niFltAnimationNode->children.length()*2));
else else
sequenceNode->setDefaultTime(niFltAnimationNode->mDuration/niFltAnimationNode->children.length()); sequenceNode->setDefaultTime(niFltAnimationNode->mDuration/niFltAnimationNode->children.length());
@ -451,7 +451,7 @@ namespace NifOsg
{ {
const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode); const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode);
osg::Sequence* sequenceNode = static_cast<osg::Sequence*>(osgNode); osg::Sequence* sequenceNode = static_cast<osg::Sequence*>(osgNode);
if (niFltAnimationNode->flags & Nif::NiFltAnimationNode::Flag_Swing) if (niFltAnimationNode->swing())
sequenceNode->setInterval(osg::Sequence::SWING, 0,-1); sequenceNode->setInterval(osg::Sequence::SWING, 0,-1);
else else
sequenceNode->setInterval(osg::Sequence::LOOP, 0,-1); sequenceNode->setInterval(osg::Sequence::LOOP, 0,-1);
@ -520,10 +520,8 @@ namespace NifOsg
if (image) if (image)
texture2d->setTextureSize(image->s(), image->t()); texture2d->setTextureSize(image->s(), image->t());
texture2d->setName("envMap"); texture2d->setName("envMap");
bool wrapT = textureEffect->clamp & 0x1; texture2d->setWrap(osg::Texture::WRAP_S, textureEffect->wrapS() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
bool wrapS = (textureEffect->clamp >> 1) & 0x1; texture2d->setWrap(osg::Texture::WRAP_T, textureEffect->wrapT() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
int texUnit = 3; // FIXME int texUnit = 3; // FIXME
@ -659,7 +657,7 @@ namespace NifOsg
// We can skip creating meshes for hidden nodes if they don't have a VisController that // We can skip creating meshes for hidden nodes if they don't have a VisController that
// might make them visible later // might make them visible later
if (nifNode->flags & Nif::NiNode::Flag_Hidden) if (nifNode->isHidden())
{ {
bool hasVisController = false; bool hasVisController = false;
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
@ -675,7 +673,7 @@ namespace NifOsg
node->setNodeMask(Loader::getHiddenNodeMask()); node->setNodeMask(Loader::getHiddenNodeMask());
} }
if (nifNode->recType == Nif::RC_NiCollisionSwitch && !(nifNode->flags & Nif::NiNode::Flag_ActiveCollision)) if (nifNode->recType == Nif::RC_NiCollisionSwitch && !nifNode->collisionActive())
node->setNodeMask(Loader::getIntersectionDisabledNodeMask()); node->setNodeMask(Loader::getIntersectionDisabledNodeMask());
osg::ref_ptr<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater; osg::ref_ptr<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater;
@ -786,7 +784,7 @@ namespace NifOsg
{ {
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
{ {
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) if (!ctrl->isActive())
continue; continue;
if (ctrl->recType == Nif::RC_NiUVController) if (ctrl->recType == Nif::RC_NiUVController)
{ {
@ -813,7 +811,7 @@ namespace NifOsg
{ {
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
{ {
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) if (!ctrl->isActive())
continue; continue;
if (ctrl->recType == Nif::RC_NiKeyframeController) if (ctrl->recType == Nif::RC_NiKeyframeController)
{ {
@ -874,7 +872,7 @@ namespace NifOsg
{ {
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
{ {
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) if (!ctrl->isActive())
continue; continue;
if (ctrl->recType == Nif::RC_NiAlphaController) if (ctrl->recType == Nif::RC_NiAlphaController)
{ {
@ -914,7 +912,7 @@ namespace NifOsg
{ {
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
{ {
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) if (!ctrl->isActive())
continue; continue;
if (ctrl->recType == Nif::RC_NiFlipController) if (ctrl->recType == Nif::RC_NiFlipController)
{ {
@ -1063,8 +1061,7 @@ namespace NifOsg
osg::ref_ptr<Emitter> handleParticleEmitter(const Nif::NiParticleSystemController* partctrl) osg::ref_ptr<Emitter> handleParticleEmitter(const Nif::NiParticleSystemController* partctrl)
{ {
std::vector<int> targets; std::vector<int> targets;
const bool atVertex = (partctrl->flags & Nif::NiNode::BSPArrayController_AtVertex); if (partctrl->recType == Nif::RC_NiBSPArrayController && !partctrl->emitAtVertex())
if (partctrl->recType == Nif::RC_NiBSPArrayController && !atVertex)
{ {
getAllNiNodes(partctrl->emitter.getPtr(), targets); getAllNiNodes(partctrl->emitter.getPtr(), targets);
} }
@ -1072,7 +1069,7 @@ namespace NifOsg
osg::ref_ptr<Emitter> emitter = new Emitter(targets); osg::ref_ptr<Emitter> emitter = new Emitter(targets);
osgParticle::ConstantRateCounter* counter = new osgParticle::ConstantRateCounter; osgParticle::ConstantRateCounter* counter = new osgParticle::ConstantRateCounter;
if (partctrl->emitFlags & Nif::NiParticleSystemController::NoAutoAdjust) if (partctrl->noAutoAdjust())
counter->setNumberOfParticlesPerSecondToCreate(partctrl->emitRate); counter->setNumberOfParticlesPerSecondToCreate(partctrl->emitRate);
else if (partctrl->lifetime == 0 && partctrl->lifetimeRandom == 0) else if (partctrl->lifetime == 0 && partctrl->lifetimeRandom == 0)
counter->setNumberOfParticlesPerSecondToCreate(0); counter->setNumberOfParticlesPerSecondToCreate(0);
@ -1089,7 +1086,7 @@ namespace NifOsg
emitter->setShooter(shooter); emitter->setShooter(shooter);
emitter->setFlags(partctrl->flags); emitter->setFlags(partctrl->flags);
if (partctrl->recType == Nif::RC_NiBSPArrayController && atVertex) if (partctrl->recType == Nif::RC_NiBSPArrayController && partctrl->emitAtVertex())
{ {
emitter->setGeometryEmitterTarget(partctrl->emitter->recIndex); emitter->setGeometryEmitterTarget(partctrl->emitter->recIndex);
} }
@ -1138,7 +1135,7 @@ namespace NifOsg
const Nif::NiParticleSystemController* partctrl = nullptr; const Nif::NiParticleSystemController* partctrl = nullptr;
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
{ {
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) if (!ctrl->isActive())
continue; continue;
if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController) if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController)
partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr()); partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr());
@ -1321,7 +1318,7 @@ namespace NifOsg
osg::ref_ptr<osg::Drawable> drawable; osg::ref_ptr<osg::Drawable> drawable;
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
{ {
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) if (!ctrl->isActive())
continue; continue;
if(ctrl->recType == Nif::RC_NiGeomMorpherController) if(ctrl->recType == Nif::RC_NiGeomMorpherController)
{ {
@ -1636,11 +1633,8 @@ namespace NifOsg
else else
texture2d = new osg::Texture2D; texture2d = new osg::Texture2D;
bool wrapT = tex.clamp & 0x1; texture2d->setWrap(osg::Texture::WRAP_S, tex.wrapS() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
bool wrapS = (tex.clamp >> 1) & 0x1; texture2d->setWrap(osg::Texture::WRAP_T, tex.wrapT() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
uvSet = tex.uvSet; uvSet = tex.uvSet;
} }
@ -1909,8 +1903,7 @@ namespace NifOsg
{ {
const Nif::NiWireframeProperty* wireprop = static_cast<const Nif::NiWireframeProperty*>(property); const Nif::NiWireframeProperty* wireprop = static_cast<const Nif::NiWireframeProperty*>(property);
osg::ref_ptr<osg::PolygonMode> mode = new osg::PolygonMode; osg::ref_ptr<osg::PolygonMode> mode = new osg::PolygonMode;
mode->setMode(osg::PolygonMode::FRONT_AND_BACK, wireprop->flags == 0 ? osg::PolygonMode::FILL mode->setMode(osg::PolygonMode::FRONT_AND_BACK, wireprop->isEnabled() ? osg::PolygonMode::LINE : osg::PolygonMode::FILL);
: osg::PolygonMode::LINE);
mode = shareAttribute(mode); mode = shareAttribute(mode);
node->getOrCreateStateSet()->setAttributeAndModes(mode, osg::StateAttribute::ON); node->getOrCreateStateSet()->setAttributeAndModes(mode, osg::StateAttribute::ON);
break; break;
@ -1919,12 +1912,9 @@ namespace NifOsg
{ {
const Nif::NiZBufferProperty* zprop = static_cast<const Nif::NiZBufferProperty*>(property); const Nif::NiZBufferProperty* zprop = static_cast<const Nif::NiZBufferProperty*>(property);
osg::StateSet* stateset = node->getOrCreateStateSet(); osg::StateSet* stateset = node->getOrCreateStateSet();
// Depth test flag stateset->setMode(GL_DEPTH_TEST, zprop->depthTest() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
stateset->setMode(GL_DEPTH_TEST, zprop->flags&1 ? osg::StateAttribute::ON
: osg::StateAttribute::OFF);
osg::ref_ptr<osg::Depth> depth = new osg::Depth; osg::ref_ptr<osg::Depth> depth = new osg::Depth;
// Depth write flag depth->setWriteMask(zprop->depthWrite());
depth->setWriteMask((zprop->flags>>1)&1);
// Morrowind ignores depth test function, unless a NiStencilProperty is present, in which case it uses a fixed depth function of GL_ALWAYS. // Morrowind ignores depth test function, unless a NiStencilProperty is present, in which case it uses a fixed depth function of GL_ALWAYS.
if (hasStencilProperty) if (hasStencilProperty)
depth->setFunction(osg::Depth::ALWAYS); depth->setFunction(osg::Depth::ALWAYS);
@ -1988,10 +1978,8 @@ namespace NifOsg
texture2d->setName("diffuseMap"); texture2d->setName("diffuseMap");
if (image) if (image)
texture2d->setTextureSize(image->s(), image->t()); texture2d->setTextureSize(image->s(), image->t());
bool wrapT = texprop->clamp & 0x1; texture2d->setWrap(osg::Texture::WRAP_S, texprop->wrapS() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
bool wrapS = (texprop->clamp >> 1) & 0x1; texture2d->setWrap(osg::Texture::WRAP_T, texprop->wrapT() ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
const unsigned int texUnit = 0; const unsigned int texUnit = 0;
const unsigned int uvSet = 0; const unsigned int uvSet = 0;
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
@ -2090,7 +2078,7 @@ namespace NifOsg
// Specular property can turn specular lighting off. // Specular property can turn specular lighting off.
// FIXME: NiMaterialColorController doesn't care about this. // FIXME: NiMaterialColorController doesn't care about this.
auto specprop = static_cast<const Nif::NiSpecularProperty*>(property); auto specprop = static_cast<const Nif::NiSpecularProperty*>(property);
specEnabled = specprop->flags & 1; specEnabled = specprop->isEnabled();
break; break;
} }
case Nif::RC_NiMaterialProperty: case Nif::RC_NiMaterialProperty:
@ -2138,10 +2126,10 @@ namespace NifOsg
case Nif::RC_NiAlphaProperty: case Nif::RC_NiAlphaProperty:
{ {
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property); const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property);
if (alphaprop->flags&1) if (alphaprop->useAlphaBlending())
{ {
osg::ref_ptr<osg::BlendFunc> blendFunc (new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf), osg::ref_ptr<osg::BlendFunc> blendFunc (new osg::BlendFunc(getBlendMode(alphaprop->sourceBlendMode()),
getBlendMode((alphaprop->flags>>5)&0xf))); getBlendMode(alphaprop->destinationBlendMode())));
// on AMD hardware, alpha still seems to be stored with an RGBA framebuffer with OpenGL. // on AMD hardware, alpha still seems to be stored with an RGBA framebuffer with OpenGL.
// This might be mandated by the OpenGL 2.1 specification section 2.14.9, or might be a bug. // This might be mandated by the OpenGL 2.1 specification section 2.14.9, or might be a bug.
// Either way, D3D8.1 doesn't do that, so adapt the destination factor. // Either way, D3D8.1 doesn't do that, so adapt the destination factor.
@ -2150,8 +2138,7 @@ namespace NifOsg
blendFunc = shareAttribute(blendFunc); blendFunc = shareAttribute(blendFunc);
node->getOrCreateStateSet()->setAttributeAndModes(blendFunc, osg::StateAttribute::ON); node->getOrCreateStateSet()->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
bool noSort = (alphaprop->flags>>13)&1; if (!alphaprop->noSorter())
if (!noSort)
{ {
hasSortAlpha = true; hasSortAlpha = true;
if (!mPushedSorter) if (!mPushedSorter)
@ -2172,9 +2159,9 @@ namespace NifOsg
blendFuncStateSet->setRenderBinToInherit(); blendFuncStateSet->setRenderBinToInherit();
} }
if((alphaprop->flags>>9)&1) if (alphaprop->useAlphaTesting())
{ {
osg::ref_ptr<osg::AlphaFunc> alphaFunc (new osg::AlphaFunc(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f)); osg::ref_ptr<osg::AlphaFunc> alphaFunc (new osg::AlphaFunc(getTestMode(alphaprop->alphaTestMode()), alphaprop->data.threshold/255.f));
alphaFunc = shareAttribute(alphaFunc); alphaFunc = shareAttribute(alphaFunc);
node->getOrCreateStateSet()->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON); node->getOrCreateStateSet()->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);
} }

@ -396,7 +396,7 @@ void Emitter::emitParticles(double dt)
osg::ref_ptr<osg::Vec3Array> geometryVertices = nullptr; osg::ref_ptr<osg::Vec3Array> geometryVertices = nullptr;
const bool useGeometryEmitter = mFlags & Nif::NiNode::BSPArrayController_AtVertex; const bool useGeometryEmitter = mFlags & Nif::NiParticleSystemController::BSPArrayController_AtVertex;
if (useGeometryEmitter || !mTargets.empty()) if (useGeometryEmitter || !mTargets.empty())
{ {
@ -445,7 +445,7 @@ void Emitter::emitParticles(double dt)
osg::NodePath path = visitor.mFoundPath; osg::NodePath path = visitor.mFoundPath;
path.erase(path.begin()); path.erase(path.begin());
if (!useGeometryEmitter && (mFlags & Nif::NiNode::BSPArrayController_AtNode) && path.size()) if (!useGeometryEmitter && (mFlags & Nif::NiParticleSystemController::BSPArrayController_AtNode) && path.size())
{ {
osg::Matrix current; osg::Matrix current;

Loading…
Cancel
Save