Rename Node->NiAVObject and update everything directly related

Update NiNode
Simplify RootCollisionNode handling in BulletNifLoader
macos_ci_fix
Alexei Kotov 1 year ago
parent 878d4ddaa7
commit a7cc4e6ba6

@ -23,18 +23,16 @@ namespace Nif::Testing
value.mController = ControllerPtr(nullptr); value.mController = ControllerPtr(nullptr);
} }
inline void init(Node& value) inline void init(NiAVObject& value)
{ {
init(static_cast<NiObjectNET&>(value)); init(static_cast<NiObjectNET&>(value));
value.flags = 0; value.mFlags = 0;
init(value.trafo); init(value.mTransform);
value.hasBounds = false;
value.isBone = false;
} }
inline void init(NiGeometry& value) inline void init(NiGeometry& value)
{ {
init(static_cast<Node&>(value)); init(static_cast<NiAVObject&>(value));
value.data = NiGeometryDataPtr(nullptr); value.data = NiGeometryDataPtr(nullptr);
value.skin = NiSkinInstancePtr(nullptr); value.skin = NiSkinInstancePtr(nullptr);
} }
@ -54,7 +52,7 @@ namespace Nif::Testing
inline void init(NiSkinInstance& value) inline void init(NiSkinInstance& value)
{ {
value.mData = NiSkinDataPtr(nullptr); value.mData = NiSkinDataPtr(nullptr);
value.mRoot = NodePtr(nullptr); value.mRoot = NiAVObjectPtr(nullptr);
} }
inline void init(Controller& value) inline void init(Controller& value)

@ -285,8 +285,8 @@ namespace
struct TestBulletNifLoader : Test struct TestBulletNifLoader : Test
{ {
BulletNifLoader mLoader; BulletNifLoader mLoader;
Nif::Node mNode; Nif::NiAVObject mNode;
Nif::Node mNode2; Nif::NiAVObject mNode2;
Nif::NiNode mNiNode; Nif::NiNode mNiNode;
Nif::NiNode mNiNode2; Nif::NiNode mNiNode2;
Nif::NiNode mNiNode3; Nif::NiNode mNiNode3;
@ -414,11 +414,10 @@ namespace
TEST_F( TEST_F(
TestBulletNifLoader, for_root_nif_node_with_bounding_box_should_return_shape_with_compound_shape_and_box_inside) TestBulletNifLoader, for_root_nif_node_with_bounding_box_should_return_shape_with_compound_shape_and_box_inside)
{ {
mNode.hasBounds = true; mNode.mFlags |= Nif::NiAVObject::Flag_BBoxCollision;
mNode.flags |= Nif::Node::Flag_BBoxCollision; mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNode); file.mRoots.push_back(&mNode);
@ -439,13 +438,12 @@ 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.mFlags |= Nif::NiAVObject::Flag_BBoxCollision;
mNode.flags |= Nif::Node::Flag_BBoxCollision; mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.mParents.push_back(&mNiNode);
mNode.parents.push_back(&mNiNode); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode) };
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -467,18 +465,16 @@ namespace
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader,
for_root_and_child_nif_node_with_bounding_box_but_root_without_flag_should_use_child_bounds) for_root_and_child_nif_node_with_bounding_box_but_root_without_flag_should_use_child_bounds)
{ {
mNode.hasBounds = true; mNode.mFlags |= Nif::NiAVObject::Flag_BBoxCollision;
mNode.flags |= Nif::Node::Flag_BBoxCollision; mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.mParents.push_back(&mNiNode);
mNode.parents.push_back(&mNiNode);
mNiNode.hasBounds = true; mNiNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNiNode.mBounds.box.extents = osg::Vec3f(4, 5, 6);
mNiNode.bounds.box.extents = osg::Vec3f(4, 5, 6); mNiNode.mBounds.box.center = osg::Vec3f(-4, -5, -6);
mNiNode.bounds.box.center = osg::Vec3f(-4, -5, -6); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode) };
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -500,24 +496,21 @@ namespace
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader,
for_root_and_two_children_where_both_with_bounds_but_only_first_with_flag_should_use_first_bounds) for_root_and_two_children_where_both_with_bounds_but_only_first_with_flag_should_use_first_bounds)
{ {
mNode.hasBounds = true; mNode.mFlags |= Nif::NiAVObject::Flag_BBoxCollision;
mNode.flags |= Nif::Node::Flag_BBoxCollision; mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.mParents.push_back(&mNiNode);
mNode.parents.push_back(&mNiNode);
mNode2.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode2.hasBounds = true; mNode2.mBounds.box.extents = osg::Vec3f(4, 5, 6);
mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode2.mBounds.box.center = osg::Vec3f(-4, -5, -6);
mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6); mNode2.mParents.push_back(&mNiNode);
mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6);
mNode2.parents.push_back(&mNiNode); mNiNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNiNode.mBounds.box.extents = osg::Vec3f(7, 8, 9);
mNiNode.hasBounds = true; mNiNode.mBounds.box.center = osg::Vec3f(-7, -8, -9);
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode), Nif::NiAVObjectPtr(&mNode2) };
mNiNode.bounds.box.extents = osg::Vec3f(7, 8, 9);
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -539,24 +532,21 @@ namespace
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader,
for_root_and_two_children_where_both_with_bounds_but_only_second_with_flag_should_use_second_bounds) for_root_and_two_children_where_both_with_bounds_but_only_second_with_flag_should_use_second_bounds)
{ {
mNode.hasBounds = true; mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.mParents.push_back(&mNiNode);
mNode.parents.push_back(&mNiNode);
mNode2.mFlags |= Nif::NiAVObject::Flag_BBoxCollision;
mNode2.hasBounds = true; mNode2.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode2.flags |= Nif::Node::Flag_BBoxCollision; mNode2.mBounds.box.extents = osg::Vec3f(4, 5, 6);
mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode2.mBounds.box.center = osg::Vec3f(-4, -5, -6);
mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6); mNode2.mParents.push_back(&mNiNode);
mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6);
mNode2.parents.push_back(&mNiNode); mNiNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNiNode.mBounds.box.extents = osg::Vec3f(7, 8, 9);
mNiNode.hasBounds = true; mNiNode.mBounds.box.center = osg::Vec3f(-7, -8, -9);
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNode), Nif::NiAVObjectPtr(&mNode2) };
mNiNode.bounds.box.extents = osg::Vec3f(7, 8, 9);
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -578,10 +568,9 @@ namespace
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader,
for_root_nif_node_with_bounds_but_without_flag_should_return_shape_with_bounds_but_with_null_collision_shape) for_root_nif_node_with_bounds_but_without_flag_should_return_shape_with_bounds_but_with_null_collision_shape)
{ {
mNode.hasBounds = true; mNode.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNode.mBounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.mBounds.box.center = osg::Vec3f(-1, -2, -3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNode); file.mRoots.push_back(&mNode);
@ -619,10 +608,9 @@ namespace
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader,
for_tri_shape_root_node_with_bounds_should_return_static_shape_with_bounds_but_with_null_collision_shape) for_tri_shape_root_node_with_bounds_should_return_static_shape_with_bounds_but_with_null_collision_shape)
{ {
mNiTriShape.hasBounds = true; mNiTriShape.mBounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
mNiTriShape.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNiTriShape.mBounds.box.extents = osg::Vec3f(1, 2, 3);
mNiTriShape.bounds.box.extents = osg::Vec3f(1, 2, 3); mNiTriShape.mBounds.box.center = osg::Vec3f(-1, -2, -3);
mNiTriShape.bounds.box.center = osg::Vec3f(-1, -2, -3);
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiTriShape); file.mRoots.push_back(&mNiTriShape);
@ -639,8 +627,8 @@ namespace
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_should_return_static_shape) TEST_F(TestBulletNifLoader, for_tri_shape_child_node_should_return_static_shape)
{ {
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -662,10 +650,10 @@ namespace
TEST_F(TestBulletNifLoader, for_nested_tri_shape_child_should_return_static_shape) TEST_F(TestBulletNifLoader, for_nested_tri_shape_child_should_return_static_shape)
{ {
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiNode2) };
mNiNode2.parents.push_back(&mNiNode); mNiNode2.mParents.push_back(&mNiNode);
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode2.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiTriShape.parents.push_back(&mNiNode2); mNiTriShape.mParents.push_back(&mNiNode2);
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -687,10 +675,9 @@ namespace
TEST_F(TestBulletNifLoader, for_two_tri_shape_children_should_return_static_shape_with_all_meshes) TEST_F(TestBulletNifLoader, for_two_tri_shape_children_should_return_static_shape_with_all_meshes)
{ {
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiTriShape2.parents.push_back(&mNiNode); mNiTriShape2.mParents.push_back(&mNiNode);
mNiNode.children mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape), Nif::NiAVObjectPtr(&mNiTriShape2) };
= Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2) }));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -717,8 +704,8 @@ namespace
for_tri_shape_child_node_and_filename_starting_with_x_and_not_empty_skin_should_return_static_shape) for_tri_shape_child_node_and_filename_starting_with_x_and_not_empty_skin_should_return_static_shape)
{ {
mNiTriShape.skin = Nif::NiSkinInstancePtr(&mNiSkinInstance); mNiTriShape.skin = Nif::NiSkinInstancePtr(&mNiSkinInstance);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -739,8 +726,8 @@ namespace
TEST_F(TestBulletNifLoader, for_tri_shape_root_node_and_filename_starting_with_x_should_return_animated_shape) TEST_F(TestBulletNifLoader, for_tri_shape_root_node_and_filename_starting_with_x_should_return_animated_shape)
{ {
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.mTransform);
mNiTriShape.trafo.mScale = 3; mNiTriShape.mTransform.mScale = 3;
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiTriShape); file.mRoots.push_back(&mNiTriShape);
@ -763,11 +750,11 @@ namespace
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_and_filename_starting_with_x_should_return_animated_shape) TEST_F(TestBulletNifLoader, for_tri_shape_child_node_and_filename_starting_with_x_should_return_animated_shape)
{ {
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.mTransform);
mNiTriShape.trafo.mScale = 3; mNiTriShape.mTransform.mScale = 3;
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiNode.trafo.mScale = 4; mNiNode.mTransform.mScale = 4;
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -791,18 +778,15 @@ namespace
TEST_F( TEST_F(
TestBulletNifLoader, for_two_tri_shape_children_nodes_and_filename_starting_with_x_should_return_animated_shape) TestBulletNifLoader, for_two_tri_shape_children_nodes_and_filename_starting_with_x_should_return_animated_shape)
{ {
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.mTransform);
mNiTriShape.trafo.mScale = 3; mNiTriShape.mTransform.mScale = 3;
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
copy(mTransform, mNiTriShape2.trafo); copy(mTransform, mNiTriShape2.mTransform);
mNiTriShape2.trafo.mScale = 3; mNiTriShape2.mTransform.mScale = 3;
mNiTriShape2.parents.push_back(&mNiNode); mNiTriShape2.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape), Nif::NiAVObjectPtr(&mNiTriShape2) };
Nif::NodePtr(&mNiTriShape),
Nif::NodePtr(&mNiTriShape2),
}));
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -834,12 +818,12 @@ namespace
{ {
mController.recType = Nif::RC_NiKeyframeController; mController.recType = Nif::RC_NiKeyframeController;
mController.flags |= Nif::Controller::Flag_Active; mController.flags |= Nif::Controller::Flag_Active;
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.mTransform);
mNiTriShape.trafo.mScale = 3; mNiTriShape.mTransform.mScale = 3;
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiTriShape.mController = Nif::ControllerPtr(&mController); mNiTriShape.mController = Nif::ControllerPtr(&mController);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiNode.trafo.mScale = 4; mNiNode.mTransform.mScale = 4;
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -864,18 +848,18 @@ namespace
{ {
mController.recType = Nif::RC_NiKeyframeController; mController.recType = Nif::RC_NiKeyframeController;
mController.flags |= Nif::Controller::Flag_Active; mController.flags |= Nif::Controller::Flag_Active;
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.mTransform);
mNiTriShape.trafo.mScale = 3; mNiTriShape.mTransform.mScale = 3;
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
copy(mTransform, mNiTriShape2.trafo); copy(mTransform, mNiTriShape2.mTransform);
mNiTriShape2.trafo.mScale = 3; mNiTriShape2.mTransform.mScale = 3;
mNiTriShape2.parents.push_back(&mNiNode); mNiTriShape2.mParents.push_back(&mNiNode);
mNiTriShape2.mController = Nif::ControllerPtr(&mController); mNiTriShape2.mController = Nif::ControllerPtr(&mController);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ mNiNode.mChildren = Nif::NiAVObjectList{
Nif::NodePtr(&mNiTriShape), Nif::NiAVObjectPtr(&mNiTriShape),
Nif::NodePtr(&mNiTriShape2), Nif::NiAVObjectPtr(&mNiTriShape2),
})); };
mNiNode.trafo.mScale = 4; mNiNode.mTransform.mScale = 4;
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -905,8 +889,8 @@ namespace
TEST_F(TestBulletNifLoader, should_add_static_mesh_to_existing_compound_mesh) TEST_F(TestBulletNifLoader, should_add_static_mesh_to_existing_compound_mesh)
{ {
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -936,8 +920,8 @@ namespace
TEST_F( TEST_F(
TestBulletNifLoader, for_root_avoid_node_and_tri_shape_child_node_should_return_shape_with_null_collision_shape) TestBulletNifLoader, for_root_avoid_node_and_tri_shape_child_node_should_return_shape_with_null_collision_shape)
{ {
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiNode.recType = Nif::RC_AvoidNode; mNiNode.recType = Nif::RC_AvoidNode;
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
@ -960,8 +944,8 @@ namespace
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_empty_data_should_return_shape_with_null_collision_shape) TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_empty_data_should_return_shape_with_null_collision_shape)
{ {
mNiTriShape.data = Nif::NiGeometryDataPtr(nullptr); mNiTriShape.data = Nif::NiGeometryDataPtr(nullptr);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -979,8 +963,8 @@ namespace
{ {
auto data = static_cast<Nif::NiTriShapeData*>(mNiTriShape.data.getPtr()); auto data = static_cast<Nif::NiTriShapeData*>(mNiTriShape.data.getPtr());
data->mTriangles.clear(); data->mTriangles.clear();
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -999,8 +983,8 @@ namespace
mNiStringExtraData.mData = "NCC__"; mNiStringExtraData.mData = "NCC__";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1028,8 +1012,8 @@ namespace
mNiStringExtraData2.mData = "NCC__"; mNiStringExtraData2.mData = "NCC__";
mNiStringExtraData2.recType = Nif::RC_NiStringExtraData; mNiStringExtraData2.recType = Nif::RC_NiStringExtraData;
mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1055,8 +1039,8 @@ namespace
mNiStringExtraData.mData = "NC___"; mNiStringExtraData.mData = "NC___";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1083,8 +1067,8 @@ namespace
mNiStringExtraData2.mData = "NC___"; mNiStringExtraData2.mData = "NC___";
mNiStringExtraData2.recType = Nif::RC_NiStringExtraData; mNiStringExtraData2.recType = Nif::RC_NiStringExtraData;
mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1112,13 +1096,13 @@ namespace
init(emptyCollisionNode); init(emptyCollisionNode);
niTriShape.data = Nif::NiGeometryDataPtr(&mNiTriShapeData); niTriShape.data = Nif::NiGeometryDataPtr(&mNiTriShapeData);
niTriShape.parents.push_back(&mNiNode); niTriShape.mParents.push_back(&mNiNode);
emptyCollisionNode.recType = Nif::RC_RootCollisionNode; emptyCollisionNode.recType = Nif::RC_RootCollisionNode;
emptyCollisionNode.parents.push_back(&mNiNode); emptyCollisionNode.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList( mNiNode.mChildren
std::vector<Nif::NodePtr>({ Nif::NodePtr(&niTriShape), Nif::NodePtr(&emptyCollisionNode) })); = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&niTriShape), Nif::NiAVObjectPtr(&emptyCollisionNode) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1144,8 +1128,8 @@ namespace
mNiStringExtraData.mData = "MRK"; mNiStringExtraData.mData = "MRK";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1163,9 +1147,9 @@ namespace
mNiIntegerExtraData.mData = 32; // BSX flag "editor marker" mNiIntegerExtraData.mData = 32; // BSX flag "editor marker"
mNiIntegerExtraData.recType = Nif::RC_BSXFlags; mNiIntegerExtraData.recType = Nif::RC_BSXFlags;
mNiTriShape.mExtraList.push_back(Nif::ExtraPtr(&mNiIntegerExtraData)); mNiTriShape.mExtraList.push_back(Nif::ExtraPtr(&mNiIntegerExtraData));
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiTriShape.mName = "EditorMarker"; mNiTriShape.mName = "EditorMarker";
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1184,11 +1168,11 @@ namespace
mNiStringExtraData.mData = "MRK"; mNiStringExtraData.mData = "MRK";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData; mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData); mNiTriShape.mExtra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode2); mNiTriShape.mParents.push_back(&mNiNode2);
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode2.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiNode2.recType = Nif::RC_RootCollisionNode; mNiNode2.recType = Nif::RC_RootCollisionNode;
mNiNode2.parents.push_back(&mNiNode); mNiNode2.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiNode2) };
mNiNode.recType = Nif::RC_NiNode; mNiNode.recType = Nif::RC_NiNode;
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
@ -1290,8 +1274,8 @@ namespace
TEST_F(TestBulletNifLoader, for_avoid_collision_mesh_should_ignore_tri_strips_data_with_less_than_3_strips) TEST_F(TestBulletNifLoader, for_avoid_collision_mesh_should_ignore_tri_strips_data_with_less_than_3_strips)
{ {
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiNode.recType = Nif::RC_AvoidNode; mNiNode.recType = Nif::RC_AvoidNode;
mNiTriStripsData.mStrips.front() = { 0, 1 }; mNiTriStripsData.mStrips.front() = { 0, 1 };
@ -1309,8 +1293,8 @@ namespace
TEST_F(TestBulletNifLoader, for_animated_mesh_should_ignore_tri_strips_data_with_less_than_3_strips) TEST_F(TestBulletNifLoader, for_animated_mesh_should_ignore_tri_strips_data_with_less_than_3_strips)
{ {
mNiTriStripsData.mStrips.front() = { 0, 1 }; mNiTriStripsData.mStrips.front() = { 0, 1 };
mNiTriStrips.parents.push_back(&mNiNode); mNiTriStrips.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriStrips) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriStrips) };
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1326,8 +1310,8 @@ namespace
TEST_F(TestBulletNifLoader, should_not_add_static_mesh_with_no_triangles_to_compound_shape) TEST_F(TestBulletNifLoader, should_not_add_static_mesh_with_no_triangles_to_compound_shape)
{ {
mNiTriStripsData.mStrips.front() = { 0, 1 }; mNiTriStripsData.mStrips.front() = { 0, 1 };
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.mParents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);
@ -1351,13 +1335,13 @@ namespace
TEST_F(TestBulletNifLoader, should_handle_node_with_multiple_parents) TEST_F(TestBulletNifLoader, should_handle_node_with_multiple_parents)
{ {
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.mTransform);
mNiTriShape.trafo.mScale = 4; mNiTriShape.mTransform.mScale = 4;
mNiTriShape.parents = { &mNiNode, &mNiNode2 }; mNiTriShape.mParents = { &mNiNode, &mNiNode2 };
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiNode.trafo.mScale = 2; mNiNode.mTransform.mScale = 2;
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode2.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) };
mNiNode2.trafo.mScale = 3; mNiNode2.mTransform.mScale = 3;
Nif::NIFFile file("xtest.nif"); Nif::NIFFile file("xtest.nif");
file.mRoots.push_back(&mNiNode); file.mRoots.push_back(&mNiNode);

@ -66,7 +66,7 @@ namespace
TEST_F(NifOsgLoaderTest, shouldLoadFileWithDefaultNode) TEST_F(NifOsgLoaderTest, shouldLoadFileWithDefaultNode)
{ {
Nif::Node node; Nif::NiAVObject node;
init(node); init(node);
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node); file.mRoots.push_back(&node);
@ -183,14 +183,14 @@ osg::Group {
TEST_P(NifOsgLoaderBSShaderPrefixTest, shouldAddShaderPrefix) TEST_P(NifOsgLoaderBSShaderPrefixTest, shouldAddShaderPrefix)
{ {
Nif::Node node; Nif::NiAVObject node;
init(node); init(node);
Nif::BSShaderPPLightingProperty property; Nif::BSShaderPPLightingProperty property;
property.recType = Nif::RC_BSShaderPPLightingProperty; property.recType = Nif::RC_BSShaderPPLightingProperty;
property.textureSet = nullptr; property.textureSet = nullptr;
property.mController = nullptr; property.mController = nullptr;
property.type = GetParam().mShaderType; property.type = GetParam().mShaderType;
node.props.push_back(Nif::RecordPtrT<Nif::Property>(&property)); node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node); file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager); auto result = Loader::load(file, &mImageManager);
@ -211,14 +211,14 @@ osg::Group {
TEST_P(NifOsgLoaderBSLightingShaderPrefixTest, shouldAddShaderPrefix) TEST_P(NifOsgLoaderBSLightingShaderPrefixTest, shouldAddShaderPrefix)
{ {
Nif::Node node; Nif::NiAVObject node;
init(node); init(node);
Nif::BSLightingShaderProperty property; Nif::BSLightingShaderProperty property;
property.recType = Nif::RC_BSLightingShaderProperty; property.recType = Nif::RC_BSLightingShaderProperty;
property.mTextureSet = nullptr; property.mTextureSet = nullptr;
property.mController = nullptr; property.mController = nullptr;
property.type = GetParam().mShaderType; property.type = GetParam().mShaderType;
node.props.push_back(Nif::RecordPtrT<Nif::Property>(&property)); node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property));
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node); file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager); auto result = Loader::load(file, &mImageManager);

@ -308,7 +308,7 @@ namespace Nif
{ {
NiInterpController::read(nif); NiInterpController::read(nif);
size_t numTargets = nif->getUShort(); size_t numTargets = nif->getUShort();
std::vector<NodePtr> targets; std::vector<NiAVObjectPtr> targets;
targets.resize(numTargets); targets.resize(numTargets);
for (size_t i = 0; i < targets.size(); i++) for (size_t i = 0; i < targets.size(); i++)
targets[i].read(nif); targets[i].read(nif);

@ -160,7 +160,7 @@ namespace Nif
osg::Vec3f offsetRandom; osg::Vec3f offsetRandom;
NodePtr emitter; NiAVObjectPtr emitter;
int numParticles; int numParticles;
int activeCount; int activeCount;
@ -211,7 +211,7 @@ namespace Nif
struct NiLookAtController : public Controller struct NiLookAtController : public Controller
{ {
NodePtr target; NiAVObjectPtr target;
unsigned short lookAtFlags{ 0 }; unsigned short lookAtFlags{ 0 };
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
@ -237,7 +237,7 @@ namespace Nif
struct NiMultiTargetTransformController : public NiInterpController struct NiMultiTargetTransformController : public NiInterpController
{ {
NodeList mExtraTargets; NiAVObjectList mExtraTargets;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;

@ -229,8 +229,8 @@ namespace Nif
{ {
NiSkinDataPtr mData; NiSkinDataPtr mData;
NiSkinPartitionPtr mPartitions; NiSkinPartitionPtr mPartitions;
NodePtr mRoot; NiAVObjectPtr mRoot;
NodeList mBones; NiAVObjectList mBones;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;

@ -8,7 +8,7 @@ namespace Nif
void NiDynamicEffect::read(NIFStream* nif) void NiDynamicEffect::read(NIFStream* nif)
{ {
Node::read(nif); NiAVObject::read(nif);
if (nif->getVersion() > NIFFile::VER_MW && nif->getVersion() < nif->generateVersion(10, 1, 0, 0)) if (nif->getVersion() > NIFFile::VER_MW && nif->getVersion() < nif->generateVersion(10, 1, 0, 0))
return; return;

@ -30,7 +30,7 @@ namespace Nif
{ {
// Abstract // Abstract
struct NiDynamicEffect : public Node struct NiDynamicEffect : public NiAVObject
{ {
bool mSwitchState{ true }; bool mSwitchState{ true };
void read(NIFStream* nif) override; void read(NIFStream* nif) override;

@ -75,51 +75,47 @@ namespace Nif
} }
} }
void Node::read(NIFStream* nif) void NiAVObject::read(NIFStream* nif)
{ {
NiObjectNET::read(nif); NiObjectNET::read(nif);
flags = nif->getBethVersion() <= 26 ? nif->getUShort() : nif->getUInt(); if (nif->getBethVersion() <= 26)
nif->read(trafo.mTranslation); mFlags = nif->get<uint16_t>();
nif->read(trafo.mRotation); else
nif->read(trafo.mScale); nif->read(mFlags);
nif->read(mTransform.mTranslation);
nif->read(mTransform.mRotation);
nif->read(mTransform.mScale);
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0)) if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
velocity = nif->getVector3(); nif->read(mVelocity);
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
readRecordList(nif, props); readRecordList(nif, mProperties);
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0) && nif->get<bool>())
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0)) mBounds.read(nif);
hasBounds = nif->getBoolean();
if (hasBounds)
bounds.read(nif);
// Reference to the collision object in Gamebryo files.
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0)) if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0))
collision.read(nif); mCollision.read(nif);
parents.clear();
isBone = false;
} }
void Node::post(Reader& nif) void NiAVObject::post(Reader& nif)
{ {
NiObjectNET::post(nif); NiObjectNET::post(nif);
postRecordList(nif, props);
collision.post(nif); postRecordList(nif, mProperties);
mCollision.post(nif);
} }
void Node::setBone() void NiAVObject::setBone()
{ {
isBone = true; mIsBone = true;
} }
void NiNode::read(NIFStream* nif) void NiNode::read(NIFStream* nif)
{ {
Node::read(nif); NiAVObject::read(nif);
readRecordList(nif, children);
readRecordList(nif, mChildren);
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4) if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
readRecordList(nif, effects); readRecordList(nif, mEffects);
// FIXME: stopgap solution until we figure out what Oblivion does if it does anything // FIXME: stopgap solution until we figure out what Oblivion does if it does anything
if (nif->getVersion() > NIFFile::NIFVersion::VER_MW && nif->getVersion() < NIFFile::NIFVersion::VER_BGS) if (nif->getVersion() > NIFFile::NIFVersion::VER_MW && nif->getVersion() < NIFFile::NIFVersion::VER_BGS)
@ -131,23 +127,24 @@ namespace Nif
// FIXME: if node 0 is *not* the only root node, this must not happen. // FIXME: if node 0 is *not* the only root node, this must not happen.
// FIXME: doing this here is awful. // FIXME: doing this here is awful.
// We want to do this on world scene graph level rather than local scene graph level. // We want to do this on world scene graph level rather than local scene graph level.
if (0 == recIndex && !Misc::StringUtils::ciEqual(mName, "bip01")) if (recIndex == 0 && !Misc::StringUtils::ciEqual(mName, "bip01"))
{ {
trafo = Nif::NiTransform::getIdentity(); mTransform = Nif::NiTransform::getIdentity();
} }
} }
void NiNode::post(Reader& nif) void NiNode::post(Reader& nif)
{ {
Node::post(nif); NiAVObject::post(nif);
postRecordList(nif, children);
postRecordList(nif, effects); postRecordList(nif, mChildren);
postRecordList(nif, mEffects);
for (auto& child : children) for (auto& child : mChildren)
{ {
// Why would a unique list of children contain empty refs? // Why would a unique list of children contain empty refs?
if (!child.empty()) if (!child.empty())
child->parents.push_back(this); child->mParents.push_back(this);
} }
} }
@ -171,7 +168,7 @@ namespace Nif
void NiGeometry::read(NIFStream* nif) void NiGeometry::read(NIFStream* nif)
{ {
Node::read(nif); NiAVObject::read(nif);
data.read(nif); data.read(nif);
skin.read(nif); skin.read(nif);
material.read(nif); material.read(nif);
@ -185,7 +182,7 @@ namespace Nif
void NiGeometry::post(Reader& nif) void NiGeometry::post(Reader& nif)
{ {
Node::post(nif); NiAVObject::post(nif);
data.post(nif); data.post(nif);
skin.post(nif); skin.post(nif);
shaderprop.post(nif); shaderprop.post(nif);
@ -224,7 +221,7 @@ namespace Nif
void NiCamera::read(NIFStream* nif) void NiCamera::read(NIFStream* nif)
{ {
Node::read(nif); NiAVObject::read(nif);
cam.read(nif); cam.read(nif);
@ -290,7 +287,7 @@ namespace Nif
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
mMode = nif->getUShort() & 0x7; mMode = nif->getUShort() & 0x7;
else else
mMode = (flags >> 5) & 0x3; mMode = (mFlags >> 5) & 0x3;
} }
void NiDefaultAVObjectPalette::read(NIFStream* nif) void NiDefaultAVObjectPalette::read(NIFStream* nif)
@ -338,7 +335,7 @@ namespace Nif
void BSTriShape::read(NIFStream* nif) void BSTriShape::read(NIFStream* nif)
{ {
Node::read(nif); NiAVObject::read(nif);
nif->read(mBoundingSphere); nif->read(mBoundingSphere);
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76) if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76)
@ -392,7 +389,7 @@ namespace Nif
void BSTriShape::post(Reader& nif) void BSTriShape::post(Reader& nif)
{ {
Node::post(nif); NiAVObject::post(nif);
mSkin.post(nif); mSkin.post(nif);
mShaderProperty.post(nif); mShaderProperty.post(nif);
mAlphaProperty.post(nif); mAlphaProperty.post(nif);

@ -51,7 +51,7 @@ namespace Nif
osg::Vec3f origin; osg::Vec3f origin;
}; };
unsigned int type; unsigned int type{ BASE_BV };
osg::BoundingSpheref sphere; osg::BoundingSpheref sphere;
NiBoxBV box; NiBoxBV box;
NiCapsuleBV capsule; NiCapsuleBV capsule;
@ -66,11 +66,9 @@ namespace Nif
{ {
}; };
/** A Node is an object that's part of the main NIF tree. It has // NiAVObject is an object that is a part of the main NIF tree. It has
parent node (unless it's the root), and transformation (location // a parent node (unless it's the root) and transformation relative to its parent.
and rotation) relative to it's parent. struct NiAVObject : public NiObjectNET
*/
struct Node : public NiObjectNET
{ {
enum Flags enum Flags
{ {
@ -80,57 +78,48 @@ namespace Nif
Flag_ActiveCollision = 0x0020 Flag_ActiveCollision = 0x0020
}; };
// Node flags. Interpretation depends somewhat on the type of node. // Node flags. Interpretation depends on the record type.
unsigned int flags; uint32_t mFlags;
NiTransform mTransform;
NiTransform trafo; osg::Vec3f mVelocity;
osg::Vec3f velocity; // Unused? Might be a run-time game state PropertyList mProperties;
PropertyList props; NiBoundingVolume mBounds;
NiCollisionObjectPtr mCollision;
// Bounding box info // Parent nodes for the node. Only types derived from NiNode can be parents.
bool hasBounds{ false }; std::vector<NiNode*> mParents;
NiBoundingVolume bounds; bool mIsBone{ false };
// Collision object info
NiCollisionObjectPtr collision;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;
// Parent node, or nullptr for the root node. As far as I'm aware, only
// NiNodes (or types derived from NiNodes) can be parents.
std::vector<NiNode*> parents;
bool isBone{ false };
void setBone(); void setBone();
bool isHidden() const { return mFlags & Flag_Hidden; }
bool isHidden() const { return flags & Flag_Hidden; } bool hasMeshCollision() const { return mFlags & Flag_MeshCollision; }
bool hasMeshCollision() const { return flags & Flag_MeshCollision; } bool hasBBoxCollision() const { return mFlags & Flag_BBoxCollision; }
bool hasBBoxCollision() const { return flags & Flag_BBoxCollision; } bool collisionActive() const { return mFlags & Flag_ActiveCollision; }
bool collisionActive() const { return flags & Flag_ActiveCollision; }
}; };
struct NiNode : Node struct NiNode : NiAVObject
{ {
NodeList children;
NodeList effects;
enum BSAnimFlags enum BSAnimFlags
{ {
AnimFlag_AutoPlay = 0x0020 AnimFlag_AutoPlay = 0x0020
}; };
enum BSParticleFlags enum BSParticleFlags
{ {
ParticleFlag_AutoPlay = 0x0020, ParticleFlag_AutoPlay = 0x0020,
ParticleFlag_LocalSpace = 0x0080 ParticleFlag_LocalSpace = 0x0080
}; };
NiAVObjectList mChildren;
NiAVObjectList mEffects;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;
}; };
struct NiGeometry : Node struct NiGeometry : NiAVObject
{ {
/* Possible flags: /* Possible flags:
0x40 - mesh has no vertex normals ? 0x40 - mesh has no vertex normals ?
@ -176,7 +165,7 @@ namespace Nif
{ {
}; };
struct NiCamera : Node struct NiCamera : NiAVObject
{ {
struct Camera struct Camera
{ {
@ -234,7 +223,7 @@ namespace Nif
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
bool swing() const { return flags & Flag_Swing; } bool swing() const { return mFlags & Flag_Swing; }
}; };
// Abstract // Abstract
@ -276,8 +265,8 @@ namespace Nif
struct NiDefaultAVObjectPalette : Record struct NiDefaultAVObjectPalette : Record
{ {
NodePtr mScene; NiAVObjectPtr mScene;
std::unordered_map<std::string, NodePtr> mObjects; std::unordered_map<std::string, NiAVObjectPtr> mObjects;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;
@ -285,7 +274,7 @@ namespace Nif
struct BSTreeNode : NiNode struct BSTreeNode : NiNode
{ {
NodeList mBones1, mBones2; NiAVObjectList mBones1, mBones2;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;
}; };
@ -350,7 +339,7 @@ namespace Nif
void read(NIFStream* nif, uint16_t flags); void read(NIFStream* nif, uint16_t flags);
}; };
struct BSTriShape : Node struct BSTriShape : NiAVObject
{ {
osg::BoundingSpheref mBoundingSphere; osg::BoundingSpheref mBoundingSphere;
std::array<float, 6> mBoundMinMax; std::array<float, 6> mBoundMinMax;
@ -397,5 +386,6 @@ namespace Nif
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
} // Namespace
}
#endif #endif

@ -374,7 +374,7 @@ namespace Nif
struct NiCollisionObject : public Record struct NiCollisionObject : public Record
{ {
// The node that references this object // The node that references this object
NodePtr mTarget; NiAVObjectPtr mTarget;
void read(NIFStream* nif) override { mTarget.read(nif); } void read(NIFStream* nif) override { mTarget.read(nif); }
void post(Reader& nif) override { mTarget.post(nif); } void post(Reader& nif) override { mTarget.post(nif); }
@ -541,7 +541,7 @@ namespace Nif
struct bhkCompressedMeshShape : public bhkShape struct bhkCompressedMeshShape : public bhkShape
{ {
NodePtr mTarget; NiAVObjectPtr mTarget;
uint32_t mUserData; uint32_t mUserData;
float mRadius; float mRadius;
osg::Vec4f mScale; osg::Vec4f mScale;

@ -110,7 +110,7 @@ namespace Nif
value.post(nif); value.post(nif);
} }
struct Node; struct NiAVObject;
struct Extra; struct Extra;
struct Property; struct Property;
struct NiUVData; struct NiUVData;
@ -152,7 +152,7 @@ namespace Nif
struct BSMultiBound; struct BSMultiBound;
struct BSMultiBoundData; struct BSMultiBoundData;
using NodePtr = RecordPtrT<Node>; using NiAVObjectPtr = RecordPtrT<NiAVObject>;
using ExtraPtr = RecordPtrT<Extra>; using ExtraPtr = RecordPtrT<Extra>;
using NiUVDataPtr = RecordPtrT<NiUVData>; using NiUVDataPtr = RecordPtrT<NiUVData>;
using NiPosDataPtr = RecordPtrT<NiPosData>; using NiPosDataPtr = RecordPtrT<NiPosData>;
@ -190,7 +190,7 @@ namespace Nif
using BSMultiBoundPtr = RecordPtrT<BSMultiBound>; using BSMultiBoundPtr = RecordPtrT<BSMultiBound>;
using BSMultiBoundDataPtr = RecordPtrT<BSMultiBoundData>; using BSMultiBoundDataPtr = RecordPtrT<BSMultiBoundData>;
using NodeList = RecordListT<Node>; using NiAVObjectList = RecordListT<NiAVObject>;
using PropertyList = RecordListT<Property>; using PropertyList = RecordListT<Property>;
using ExtraList = RecordListT<Extra>; using ExtraList = RecordListT<Extra>;
using NiSourceTextureList = RecordListT<NiSourceTexture>; using NiSourceTextureList = RecordListT<NiSourceTexture>;

@ -132,13 +132,13 @@ namespace NifBullet
mShape->mFileHash = nif.getHash(); mShape->mFileHash = nif.getHash();
const size_t numRoots = nif.numRoots(); const size_t numRoots = nif.numRoots();
std::vector<const Nif::Node*> roots; std::vector<const Nif::NiAVObject*> roots;
for (size_t i = 0; i < numRoots; ++i) for (size_t i = 0; i < numRoots; ++i)
{ {
const Nif::Record* r = nif.getRoot(i); const Nif::Record* r = nif.getRoot(i);
if (!r) if (!r)
continue; continue;
const Nif::Node* node = dynamic_cast<const Nif::Node*>(r); const Nif::NiAVObject* node = dynamic_cast<const Nif::NiAVObject*>(r);
if (node) if (node)
roots.emplace_back(node); roots.emplace_back(node);
} }
@ -151,7 +151,7 @@ namespace NifBullet
} }
// Try to find a valid bounding box first. If one's found for any root node, use that. // Try to find a valid bounding box first. If one's found for any root node, use that.
for (const Nif::Node* node : roots) for (const Nif::NiAVObject* node : roots)
{ {
if (findBoundingBox(*node, filename)) if (findBoundingBox(*node, filename))
{ {
@ -175,15 +175,19 @@ namespace NifBullet
// If there's no bounding box, we'll have to generate a Bullet collision shape // If there's no bounding box, we'll have to generate a Bullet collision shape
// from the collision data present in every root node. // from the collision data present in every root node.
for (const Nif::Node* node : roots) for (const Nif::NiAVObject* node : roots)
{ {
bool hasCollisionNode = hasRootCollisionNode(*node); const Nif::NiNode* colNode = findRootCollisionNode(*node);
bool hasCollisionShape = hasCollisionNode && !collisionShapeIsEmpty(*node); bool hasCollisionShape = false;
if (hasCollisionNode && !hasCollisionShape) if (colNode != nullptr)
{
if (colNode->mBounds.type == Nif::NiBoundingVolume::Type::BASE_BV && !colNode->mChildren.empty())
hasCollisionShape = true;
else
mShape->mVisualCollisionType = Resource::VisualCollisionType::Camera; mShape->mVisualCollisionType = Resource::VisualCollisionType::Camera;
bool generateCollisionShape = !hasCollisionShape; }
HandleNodeArgs args; HandleNodeArgs args;
args.mAutogenerated = args.mIsCollisionNode = generateCollisionShape; args.mAutogenerated = args.mIsCollisionNode = !hasCollisionShape;
args.mAnimated = isAnimated; args.mAnimated = isAnimated;
handleNode(filename, *node, nullptr, args, mShape->mVisualCollisionType); handleNode(filename, *node, nullptr, args, mShape->mVisualCollisionType);
} }
@ -199,16 +203,16 @@ namespace NifBullet
// Find a boundingBox in the node hierarchy. // Find a boundingBox in the node hierarchy.
// Return: use bounding box for collision? // Return: use bounding box for collision?
bool BulletNifLoader::findBoundingBox(const Nif::Node& node, const std::string& filename) bool BulletNifLoader::findBoundingBox(const Nif::NiAVObject& node, const std::string& filename)
{
if (node.hasBounds)
{ {
unsigned int type = node.bounds.type; unsigned int type = node.mBounds.type;
switch (type) switch (type)
{ {
case Nif::NiBoundingVolume::Type::BASE_BV:
break;
case Nif::NiBoundingVolume::Type::BOX_BV: case Nif::NiBoundingVolume::Type::BOX_BV:
mShape->mCollisionBox.mExtents = node.bounds.box.extents; mShape->mCollisionBox.mExtents = node.mBounds.box.extents;
mShape->mCollisionBox.mCenter = node.bounds.box.center; mShape->mCollisionBox.mCenter = node.mBounds.box.center;
break; break;
default: default:
{ {
@ -219,59 +223,33 @@ namespace NifBullet
} }
} }
if (node.hasBBoxCollision()) if (type != Nif::NiBoundingVolume::Type::BASE_BV && node.hasBBoxCollision())
{
return true; return true;
}
}
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&node)) if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&node))
{ {
const Nif::NodeList& list = ninode->children; for (const auto& child : ninode->mChildren)
for (const auto& child : list)
if (!child.empty() && findBoundingBox(child.get(), filename)) if (!child.empty() && findBoundingBox(child.get(), filename))
return true; return true;
} }
return false; return false;
} }
bool BulletNifLoader::hasRootCollisionNode(const Nif::Node& rootNode) const const Nif::NiNode* BulletNifLoader::findRootCollisionNode(const Nif::NiAVObject& rootNode) const
{ {
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode)) if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
{ {
for (const auto& child : ninode->children) for (const auto& child : ninode->mChildren)
{ {
if (child.empty()) if (!child.empty() && child.getPtr()->recType == Nif::RC_RootCollisionNode)
continue; return static_cast<const Nif::NiNode*>(child.getPtr());
if (child.getPtr()->recType == Nif::RC_RootCollisionNode)
return true;
}
} }
return false;
} }
return nullptr;
bool BulletNifLoader::collisionShapeIsEmpty(const Nif::Node& rootNode) const
{
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
{
for (const auto& child : ninode->children)
{
if (child.empty())
continue;
const Nif::Node* childNode = child.getPtr();
if (childNode->recType != Nif::RC_RootCollisionNode)
continue;
const Nif::NiNode* niChildnode
= static_cast<const Nif::NiNode*>(childNode); // RootCollisionNode is always a NiNode
if (childNode->hasBounds || niChildnode->children.size() > 0)
return false;
}
}
return true;
} }
void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent, void BulletNifLoader::handleNode(const std::string& fileName, const Nif::NiAVObject& node,
HandleNodeArgs args, Resource::VisualCollisionType& visualCollisionType) const Nif::Parent* parent, HandleNodeArgs args, Resource::VisualCollisionType& visualCollisionType)
{ {
// 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.collisionActive()) if (node.recType == Nif::RC_NiCollisionSwitch && !node.collisionActive())
@ -354,10 +332,10 @@ namespace NifBullet
if (args.mIsCollisionNode) if (args.mIsCollisionNode)
{ {
// NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape! // NOTE: a trishape with bounds, but no BBoxCollision flag should NOT go through handleNiTriShape!
// It must be ignored completely. // It must be ignored completely.
// (occurs in tr_ex_imp_wall_arch_04.nif) // (occurs in tr_ex_imp_wall_arch_04.nif)
if (!node.hasBounds if (node.mBounds.type == Nif::NiBoundingVolume::Type::BASE_BV
&& (node.recType == Nif::RC_NiTriShape || node.recType == Nif::RC_NiTriStrips && (node.recType == Nif::RC_NiTriShape || node.recType == Nif::RC_NiTriStrips
|| node.recType == Nif::RC_BSLODTriShape)) || node.recType == Nif::RC_BSLODTriShape))
{ {
@ -368,14 +346,13 @@ namespace NifBullet
// For NiNodes, loop through children // For NiNodes, loop through children
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&node)) if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&node))
{ {
const Nif::NodeList& list = ninode->children;
const Nif::Parent currentParent{ *ninode, parent }; const Nif::Parent currentParent{ *ninode, parent };
for (const auto& child : list) for (const auto& child : ninode->mChildren)
{ {
if (child.empty()) if (child.empty())
continue; continue;
assert(std::find(child->parents.begin(), child->parents.end(), ninode) != child->parents.end()); assert(std::find(child->mParents.begin(), child->mParents.end(), ninode) != child->mParents.end());
handleNode(fileName, child.get(), &currentParent, args, visualCollisionType); handleNode(fileName, child.get(), &currentParent, args, visualCollisionType);
} }
} }
@ -403,9 +380,9 @@ namespace NifBullet
auto childShape = std::make_unique<Resource::TriangleMeshShape>(childMesh.get(), true); auto childShape = std::make_unique<Resource::TriangleMeshShape>(childMesh.get(), true);
std::ignore = childMesh.release(); std::ignore = childMesh.release();
osg::Matrixf transform = niGeometry.trafo.toMatrix(); osg::Matrixf transform = niGeometry.mTransform.toMatrix();
for (const Nif::Parent* parent = nodeParent; parent != nullptr; parent = parent->mParent) for (const Nif::Parent* parent = nodeParent; parent != nullptr; parent = parent->mParent)
transform *= parent->mNiNode.trafo.toMatrix(); transform *= parent->mNiNode.mTransform.toMatrix();
childShape->setLocalScaling(Misc::Convert::toBullet(transform.getScale())); childShape->setLocalScaling(Misc::Convert::toBullet(transform.getScale()));
transform.orthoNormalize(transform); transform.orthoNormalize(transform);

@ -22,10 +22,8 @@ class btCollisionShape;
namespace Nif namespace Nif
{ {
struct Node; struct NiAVObject;
struct Transformation; struct NiNode;
struct NiTriShape;
struct NiTriStrips;
struct NiGeometry; struct NiGeometry;
struct Parent; struct Parent;
} }
@ -50,7 +48,7 @@ namespace NifBullet
osg::ref_ptr<Resource::BulletShape> load(Nif::FileView file); osg::ref_ptr<Resource::BulletShape> load(Nif::FileView file);
private: private:
bool findBoundingBox(const Nif::Node& node, const std::string& filename); bool findBoundingBox(const Nif::NiAVObject& node, const std::string& filename);
struct HandleNodeArgs struct HandleNodeArgs
{ {
@ -61,11 +59,10 @@ namespace NifBullet
bool mAvoid{ false }; bool mAvoid{ false };
}; };
void handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent, void handleNode(const std::string& fileName, const Nif::NiAVObject& node, const Nif::Parent* parent,
HandleNodeArgs args, Resource::VisualCollisionType& visualCollisionType); HandleNodeArgs args, Resource::VisualCollisionType& visualCollisionType);
bool hasRootCollisionNode(const Nif::Node& rootNode) const; const Nif::NiNode* findRootCollisionNode(const Nif::NiAVObject& rootNode) const;
bool collisionShapeIsEmpty(const Nif::Node& rootNode) const;
void handleNiTriShape(const Nif::NiGeometry& nifNode, const Nif::Parent* parent, HandleNodeArgs args); void handleNiTriShape(const Nif::NiGeometry& nifNode, const Nif::Parent* parent, HandleNodeArgs args);

@ -76,12 +76,12 @@ namespace
void apply(osg::Drawable& node) override { traverse(node); } void apply(osg::Drawable& node) override { traverse(node); }
}; };
void getAllNiNodes(const Nif::Node* node, std::vector<int>& outIndices) void getAllNiNodes(const Nif::NiAVObject* node, std::vector<int>& outIndices)
{ {
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(node)) if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(node))
{ {
outIndices.push_back(ninode->recIndex); outIndices.push_back(ninode->recIndex);
for (const auto& child : ninode->children) for (const auto& child : ninode->mChildren)
if (!child.empty()) if (!child.empty())
getAllNiNodes(child.getPtr(), outIndices); getAllNiNodes(child.getPtr(), outIndices);
} }
@ -103,11 +103,11 @@ namespace
// Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the // Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the
// node hierarchy above it. // node hierarchy above it.
void collectDrawableProperties( void collectDrawableProperties(
const Nif::Node* nifNode, const Nif::Parent* parent, std::vector<const Nif::Property*>& out) const Nif::NiAVObject* nifNode, const Nif::Parent* parent, std::vector<const Nif::Property*>& out)
{ {
if (parent != nullptr) if (parent != nullptr)
collectDrawableProperties(&parent->mNiNode, parent->mParent, out); collectDrawableProperties(&parent->mNiNode, parent->mParent, out);
for (const auto& property : nifNode->props) for (const auto& property : nifNode->mProperties)
{ {
if (!property.empty()) if (!property.empty())
{ {
@ -345,13 +345,13 @@ namespace NifOsg
osg::ref_ptr<osg::Node> load(Nif::FileView nif, Resource::ImageManager* imageManager) osg::ref_ptr<osg::Node> load(Nif::FileView nif, Resource::ImageManager* imageManager)
{ {
const size_t numRoots = nif.numRoots(); const size_t numRoots = nif.numRoots();
std::vector<const Nif::Node*> roots; std::vector<const Nif::NiAVObject*> roots;
for (size_t i = 0; i < numRoots; ++i) for (size_t i = 0; i < numRoots; ++i)
{ {
const Nif::Record* r = nif.getRoot(i); const Nif::Record* r = nif.getRoot(i);
if (!r) if (!r)
continue; continue;
const Nif::Node* nifNode = dynamic_cast<const Nif::Node*>(r); const Nif::NiAVObject* nifNode = dynamic_cast<const Nif::NiAVObject*>(r);
if (nifNode) if (nifNode)
roots.emplace_back(nifNode); roots.emplace_back(nifNode);
} }
@ -362,7 +362,7 @@ namespace NifOsg
osg::ref_ptr<osg::Group> created(new osg::Group); osg::ref_ptr<osg::Group> created(new osg::Group);
created->setDataVariance(osg::Object::STATIC); created->setDataVariance(osg::Object::STATIC);
for (const Nif::Node* root : roots) for (const Nif::NiAVObject* root : roots)
{ {
auto node = handleNode(root, nullptr, nullptr, auto node = handleNode(root, nullptr, nullptr,
{ .mNifVersion = nif.getVersion(), { .mNifVersion = nif.getVersion(),
@ -397,13 +397,13 @@ namespace NifOsg
return created; return created;
} }
void applyNodeProperties(const Nif::Node* nifNode, osg::Node* applyTo, void applyNodeProperties(const Nif::NiAVObject* nifNode, osg::Node* applyTo,
SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager, SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager,
std::vector<unsigned int>& boundTextures, int animflags) std::vector<unsigned int>& boundTextures, int animflags)
{ {
bool hasStencilProperty = false; bool hasStencilProperty = false;
for (const auto& property : nifNode->props) for (const auto& property : nifNode->mProperties)
{ {
if (property.empty()) if (property.empty())
continue; continue;
@ -420,13 +420,13 @@ namespace NifOsg
} }
} }
for (const auto& property : nifNode->props) for (const auto& property : nifNode->mProperties)
{ {
if (!property.empty()) if (!property.empty())
{ {
// Get the lowest numbered recIndex of the NiTexturingProperty root node. // Get the lowest numbered recIndex of the NiTexturingProperty root node.
// This is what is overridden when a spell effect "particle texture" is used. // This is what is overridden when a spell effect "particle texture" is used.
if (nifNode->parents.empty() && !mFoundFirstRootTexturingProperty if (nifNode->mParents.empty() && !mFoundFirstRootTexturingProperty
&& property.getPtr()->recType == Nif::RC_NiTexturingProperty) && property.getPtr()->recType == Nif::RC_NiTexturingProperty)
{ {
mFirstRootTextureIndex = property.getPtr()->recIndex; mFirstRootTextureIndex = property.getPtr()->recIndex;
@ -482,23 +482,23 @@ namespace NifOsg
return switchNode; return switchNode;
} }
static osg::ref_ptr<osg::Sequence> prepareSequenceNode(const Nif::Node* nifNode) static osg::ref_ptr<osg::Sequence> prepareSequenceNode(const Nif::NiAVObject* nifNode)
{ {
const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode); const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode);
osg::ref_ptr<osg::Sequence> sequenceNode(new osg::Sequence); osg::ref_ptr<osg::Sequence> sequenceNode(new osg::Sequence);
sequenceNode->setName(niFltAnimationNode->mName); sequenceNode->setName(niFltAnimationNode->mName);
if (!niFltAnimationNode->children.empty()) if (!niFltAnimationNode->mChildren.empty())
{ {
if (niFltAnimationNode->swing()) if (niFltAnimationNode->swing())
sequenceNode->setDefaultTime( sequenceNode->setDefaultTime(
niFltAnimationNode->mDuration / (niFltAnimationNode->children.size() * 2)); niFltAnimationNode->mDuration / (niFltAnimationNode->mChildren.size() * 2));
else else
sequenceNode->setDefaultTime(niFltAnimationNode->mDuration / niFltAnimationNode->children.size()); sequenceNode->setDefaultTime(niFltAnimationNode->mDuration / niFltAnimationNode->mChildren.size());
} }
return sequenceNode; return sequenceNode;
} }
static void activateSequenceNode(osg::Group* osgNode, const Nif::Node* nifNode) static void activateSequenceNode(osg::Group* osgNode, const Nif::NiAVObject* nifNode)
{ {
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);
@ -535,7 +535,7 @@ namespace NifOsg
texture->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
} }
bool handleEffect(const Nif::Node* nifNode, osg::StateSet* stateset, Resource::ImageManager* imageManager) bool handleEffect(const Nif::NiAVObject* nifNode, osg::StateSet* stateset, Resource::ImageManager* imageManager)
{ {
if (nifNode->recType != Nif::RC_NiTextureEffect) if (nifNode->recType != Nif::RC_NiTextureEffect)
{ {
@ -596,7 +596,7 @@ namespace NifOsg
} }
// Get a default dataVariance for this node to be used as a hint by optimization (post)routines // Get a default dataVariance for this node to be used as a hint by optimization (post)routines
osg::ref_ptr<osg::Group> createNode(const Nif::Node* nifNode) osg::ref_ptr<osg::Group> createNode(const Nif::NiAVObject* nifNode)
{ {
osg::ref_ptr<osg::Group> node; osg::ref_ptr<osg::Group> node;
osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED; osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED;
@ -611,15 +611,15 @@ namespace NifOsg
// This takes advantage of the fact root nodes can't have additional controllers // This takes advantage of the fact root nodes can't have additional controllers
// loaded from an external .kf file (original engine just throws "can't find node" errors if you // loaded from an external .kf file (original engine just throws "can't find node" errors if you
// try). // try).
if (nifNode->parents.empty() && nifNode->mController.empty() && nifNode->trafo.isIdentity()) if (nifNode->mParents.empty() && nifNode->mController.empty() && nifNode->mTransform.isIdentity())
node = new osg::Group; node = new osg::Group;
dataVariance = nifNode->isBone ? osg::Object::DYNAMIC : osg::Object::STATIC; dataVariance = nifNode->mIsBone ? osg::Object::DYNAMIC : osg::Object::STATIC;
break; break;
} }
if (!node) if (!node)
node = new NifOsg::MatrixTransform(nifNode->trafo); node = new NifOsg::MatrixTransform(nifNode->mTransform);
node->setDataVariance(dataVariance); node->setDataVariance(dataVariance);
@ -627,7 +627,7 @@ namespace NifOsg
} }
osg::ref_ptr<osg::Node> handleNode( osg::ref_ptr<osg::Node> handleNode(
const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args) const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args)
{ {
if (args.mRootNode && Misc::StringUtils::ciEqual(nifNode->mName, "Bounding Box")) if (args.mRootNode && Misc::StringUtils::ciEqual(nifNode->mName, "Bounding Box"))
return nullptr; return nullptr;
@ -692,7 +692,7 @@ namespace NifOsg
} }
if (nifNode->recType == Nif::RC_NiBSAnimationNode || nifNode->recType == Nif::RC_NiBSParticleNode) if (nifNode->recType == Nif::RC_NiBSAnimationNode || nifNode->recType == Nif::RC_NiBSParticleNode)
args.mAnimFlags = nifNode->flags; args.mAnimFlags = nifNode->mFlags;
if (nifNode->recType == Nif::RC_NiSortAdjustNode) if (nifNode->recType == Nif::RC_NiSortAdjustNode)
{ {
@ -829,7 +829,7 @@ namespace NifOsg
const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(nifNode); const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
if (ninode) if (ninode)
{ {
const Nif::NodeList& children = ninode->children; const Nif::NiAVObjectList& children = ninode->mChildren;
const Nif::Parent currentParent{ *ninode, parent }; const Nif::Parent currentParent{ *ninode, parent };
for (const auto& child : children) for (const auto& child : children)
if (!child.empty()) if (!child.empty())
@ -838,7 +838,7 @@ namespace NifOsg
// Propagate effects to the the direct subgraph instead of the node itself // Propagate effects to the the direct subgraph instead of the node itself
// This simulates their "affected node list" which Morrowind appears to replace with the subgraph (?) // This simulates their "affected node list" which Morrowind appears to replace with the subgraph (?)
// Note that the serialized affected node list is actually unused // Note that the serialized affected node list is actually unused
for (const auto& effect : ninode->effects) for (const auto& effect : ninode->mEffects)
if (!effect.empty()) if (!effect.empty())
{ {
osg::ref_ptr<osg::StateSet> effectStateSet = new osg::StateSet; osg::ref_ptr<osg::StateSet> effectStateSet = new osg::StateSet;
@ -854,7 +854,7 @@ namespace NifOsg
return node; return node;
} }
void handleMeshControllers(const Nif::Node* nifNode, osg::Node* node, void handleMeshControllers(const Nif::NiAVObject* nifNode, osg::Node* node,
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
int animflags) int animflags)
{ {
@ -883,7 +883,7 @@ namespace NifOsg
} }
} }
void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated) void handleNodeControllers(const Nif::NiAVObject* nifNode, osg::Node* node, int animflags, bool& isAnimated)
{ {
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
{ {
@ -1121,7 +1121,7 @@ namespace NifOsg
// Load the initial state of the particle system, i.e. the initial particles and their positions, velocity and // Load the initial state of the particle system, i.e. the initial particles and their positions, velocity and
// colors. // colors.
void handleParticleInitialState( void handleParticleInitialState(
const Nif::Node* nifNode, ParticleSystem* partsys, const Nif::NiParticleSystemController* partctrl) const Nif::NiAVObject* nifNode, ParticleSystem* partsys, const Nif::NiParticleSystemController* partctrl)
{ {
auto particleNode = static_cast<const Nif::NiParticles*>(nifNode); auto particleNode = static_cast<const Nif::NiParticles*>(nifNode);
if (particleNode->data.empty() || particleNode->data->recType != Nif::RC_NiParticlesData) if (particleNode->data.empty() || particleNode->data->recType != Nif::RC_NiParticlesData)
@ -1247,7 +1247,7 @@ namespace NifOsg
mEmitterQueue.clear(); mEmitterQueue.clear();
} }
void handleParticleSystem(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, void handleParticleSystem(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode,
SceneUtil::CompositeStateSetUpdater* composite, int animflags) SceneUtil::CompositeStateSetUpdater* composite, int animflags)
{ {
osg::ref_ptr<ParticleSystem> partsys(new ParticleSystem); osg::ref_ptr<ParticleSystem> partsys(new ParticleSystem);
@ -1375,7 +1375,7 @@ namespace NifOsg
} }
} }
void handleNiGeometry(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Geometry* geometry, void handleNiGeometry(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Geometry* geometry,
osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite,
const std::vector<unsigned int>& boundTextures, int animflags) const std::vector<unsigned int>& boundTextures, int animflags)
{ {
@ -1474,7 +1474,7 @@ namespace NifOsg
applyDrawableProperties(parentNode, drawableProps, composite, !niGeometryData->mColors.empty(), animflags); applyDrawableProperties(parentNode, drawableProps, composite, !niGeometryData->mColors.empty(), animflags);
} }
void handleGeometry(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, void handleGeometry(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode,
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
int animflags) int animflags)
{ {
@ -1530,7 +1530,7 @@ namespace NifOsg
return morphGeom; return morphGeom;
} }
void handleSkinnedGeometry(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, void handleSkinnedGeometry(const Nif::NiAVObject* nifNode, const Nif::Parent* parent, osg::Group* parentNode,
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
int animflags) int animflags)
{ {
@ -1548,7 +1548,7 @@ namespace NifOsg
const Nif::NiSkinInstance* skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin.getPtr(); const Nif::NiSkinInstance* skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin.getPtr();
const Nif::NiSkinData* data = skin->mData.getPtr(); const Nif::NiSkinData* data = skin->mData.getPtr();
const Nif::NodeList& bones = skin->mBones; const Nif::NiAVObjectList& bones = skin->mBones;
for (std::size_t i = 0; i < bones.size(); ++i) for (std::size_t i = 0; i < bones.size(); ++i)
{ {
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName); std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);

Loading…
Cancel
Save