mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-27 04:40:26 +00:00
Merge branch 'nif_multi_parents' into 'master'
Support multiple parents for NIF nodes (#6552) Closes #6552 See merge request OpenMW/openmw!1577
This commit is contained in:
commit
21ef9d4058
6 changed files with 156 additions and 76 deletions
|
@ -277,7 +277,7 @@ namespace
|
||||||
value.flags = 0;
|
value.flags = 0;
|
||||||
init(value.trafo);
|
init(value.trafo);
|
||||||
value.hasBounds = false;
|
value.hasBounds = false;
|
||||||
value.parent = nullptr;
|
value.parents.push_back(nullptr);
|
||||||
value.isBone = false;
|
value.isBone = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +512,7 @@ namespace
|
||||||
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);
|
||||||
mNode.parent = &mNiNode;
|
mNode.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNode)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNode)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -538,7 +538,7 @@ namespace
|
||||||
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);
|
||||||
mNode.parent = &mNiNode;
|
mNode.parents.push_back(&mNiNode);
|
||||||
|
|
||||||
mNiNode.hasBounds = true;
|
mNiNode.hasBounds = true;
|
||||||
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
|
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
|
||||||
|
@ -569,13 +569,13 @@ namespace
|
||||||
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);
|
||||||
mNode.parent = &mNiNode;
|
mNode.parents.push_back(&mNiNode);
|
||||||
|
|
||||||
mNode2.hasBounds = true;
|
mNode2.hasBounds = true;
|
||||||
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);
|
||||||
mNode2.parent = &mNiNode;
|
mNode2.parents.push_back(&mNiNode);
|
||||||
|
|
||||||
mNiNode.hasBounds = true;
|
mNiNode.hasBounds = true;
|
||||||
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
|
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
|
||||||
|
@ -605,14 +605,14 @@ namespace
|
||||||
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);
|
||||||
mNode.parent = &mNiNode;
|
mNode.parents.push_back(&mNiNode);
|
||||||
|
|
||||||
mNode2.hasBounds = true;
|
mNode2.hasBounds = true;
|
||||||
mNode2.flags |= Nif::NiNode::Flag_BBoxCollision;
|
mNode2.flags |= Nif::NiNode::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);
|
||||||
mNode2.parent = &mNiNode;
|
mNode2.parents.push_back(&mNiNode);
|
||||||
|
|
||||||
mNiNode.hasBounds = true;
|
mNiNode.hasBounds = true;
|
||||||
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
|
mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
|
||||||
|
@ -691,7 +691,7 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_should_return_shape_with_triangle_mesh_shape)
|
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_should_return_shape_with_triangle_mesh_shape)
|
||||||
{
|
{
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -710,9 +710,9 @@ namespace
|
||||||
TEST_F(TestBulletNifLoader, for_nested_tri_shape_child_should_return_shape_with_triangle_mesh_shape)
|
TEST_F(TestBulletNifLoader, for_nested_tri_shape_child_should_return_shape_with_triangle_mesh_shape)
|
||||||
{
|
{
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiNode2)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiNode2)}));
|
||||||
mNiNode2.parent = &mNiNode;
|
mNiNode2.parents.push_back(&mNiNode);
|
||||||
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
mNiTriShape.parent = &mNiNode2;
|
mNiTriShape.parents.push_back(&mNiNode2);
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
||||||
|
@ -729,8 +729,8 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_two_tri_shape_children_should_return_shape_with_triangle_mesh_shape_with_all_meshes)
|
TEST_F(TestBulletNifLoader, for_two_tri_shape_children_should_return_shape_with_triangle_mesh_shape_with_all_meshes)
|
||||||
{
|
{
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiTriShape2.parent = &mNiNode;
|
mNiTriShape2.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({
|
||||||
Nif::NodePtr(&mNiTriShape),
|
Nif::NodePtr(&mNiTriShape),
|
||||||
Nif::NodePtr(&mNiTriShape2)
|
Nif::NodePtr(&mNiTriShape2)
|
||||||
|
@ -753,7 +753,7 @@ namespace
|
||||||
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_and_filename_starting_with_x_and_not_empty_skin_should_return_shape_with_triangle_mesh_shape)
|
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_and_filename_starting_with_x_and_not_empty_skin_should_return_shape_with_triangle_mesh_shape)
|
||||||
{
|
{
|
||||||
mNiTriShape.skin = Nif::NiSkinInstancePtr(&mNiSkinInstance);
|
mNiTriShape.skin = Nif::NiSkinInstancePtr(&mNiSkinInstance);
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -796,7 +796,7 @@ namespace
|
||||||
{
|
{
|
||||||
copy(mTransform, mNiTriShape.trafo);
|
copy(mTransform, mNiTriShape.trafo);
|
||||||
mNiTriShape.trafo.scale = 3;
|
mNiTriShape.trafo.scale = 3;
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
mNiNode.trafo.scale = 4;
|
mNiNode.trafo.scale = 4;
|
||||||
|
|
||||||
|
@ -822,11 +822,11 @@ namespace
|
||||||
{
|
{
|
||||||
copy(mTransform, mNiTriShape.trafo);
|
copy(mTransform, mNiTriShape.trafo);
|
||||||
mNiTriShape.trafo.scale = 3;
|
mNiTriShape.trafo.scale = 3;
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
|
|
||||||
copy(mTransform, mNiTriShape2.trafo);
|
copy(mTransform, mNiTriShape2.trafo);
|
||||||
mNiTriShape2.trafo.scale = 3;
|
mNiTriShape2.trafo.scale = 3;
|
||||||
mNiTriShape2.parent = &mNiNode;
|
mNiTriShape2.parents.push_back(&mNiNode);
|
||||||
|
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({
|
||||||
Nif::NodePtr(&mNiTriShape),
|
Nif::NodePtr(&mNiTriShape),
|
||||||
|
@ -864,7 +864,7 @@ namespace
|
||||||
mController.flags |= Nif::NiNode::ControllerFlag_Active;
|
mController.flags |= Nif::NiNode::ControllerFlag_Active;
|
||||||
copy(mTransform, mNiTriShape.trafo);
|
copy(mTransform, mNiTriShape.trafo);
|
||||||
mNiTriShape.trafo.scale = 3;
|
mNiTriShape.trafo.scale = 3;
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiTriShape.controller = Nif::ControllerPtr(&mController);
|
mNiTriShape.controller = Nif::ControllerPtr(&mController);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
mNiNode.trafo.scale = 4;
|
mNiNode.trafo.scale = 4;
|
||||||
|
@ -893,10 +893,10 @@ namespace
|
||||||
mController.flags |= Nif::NiNode::ControllerFlag_Active;
|
mController.flags |= Nif::NiNode::ControllerFlag_Active;
|
||||||
copy(mTransform, mNiTriShape.trafo);
|
copy(mTransform, mNiTriShape.trafo);
|
||||||
mNiTriShape.trafo.scale = 3;
|
mNiTriShape.trafo.scale = 3;
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
copy(mTransform, mNiTriShape2.trafo);
|
copy(mTransform, mNiTriShape2.trafo);
|
||||||
mNiTriShape2.trafo.scale = 3;
|
mNiTriShape2.trafo.scale = 3;
|
||||||
mNiTriShape2.parent = &mNiNode;
|
mNiTriShape2.parents.push_back(&mNiNode);
|
||||||
mNiTriShape2.controller = Nif::ControllerPtr(&mController);
|
mNiTriShape2.controller = Nif::ControllerPtr(&mController);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({
|
||||||
Nif::NodePtr(&mNiTriShape),
|
Nif::NodePtr(&mNiTriShape),
|
||||||
|
@ -931,7 +931,7 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, should_add_static_mesh_to_existing_compound_mesh)
|
TEST_F(TestBulletNifLoader, should_add_static_mesh_to_existing_compound_mesh)
|
||||||
{
|
{
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
||||||
|
@ -959,7 +959,7 @@ namespace
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_root_avoid_node_and_tri_shape_child_node_should_return_shape_with_null_collision_shape)
|
TEST_F(TestBulletNifLoader, for_root_avoid_node_and_tri_shape_child_node_should_return_shape_with_null_collision_shape)
|
||||||
{
|
{
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
mNiNode.recType = Nif::RC_AvoidNode;
|
mNiNode.recType = Nif::RC_AvoidNode;
|
||||||
|
|
||||||
|
@ -979,7 +979,7 @@ 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.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -996,7 +996,7 @@ namespace
|
||||||
{
|
{
|
||||||
auto data = static_cast<Nif::NiTriShapeData*>(mNiTriShape.data.getPtr());
|
auto data = static_cast<Nif::NiTriShapeData*>(mNiTriShape.data.getPtr());
|
||||||
data->triangles.clear();
|
data->triangles.clear();
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -1014,7 +1014,7 @@ namespace
|
||||||
mNiStringExtraData.string = "NC___";
|
mNiStringExtraData.string = "NC___";
|
||||||
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
||||||
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -1033,7 +1033,7 @@ namespace
|
||||||
mNiStringExtraData2.string = "NC___";
|
mNiStringExtraData2.string = "NC___";
|
||||||
mNiStringExtraData2.recType = Nif::RC_NiStringExtraData;
|
mNiStringExtraData2.recType = Nif::RC_NiStringExtraData;
|
||||||
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -1051,7 +1051,7 @@ namespace
|
||||||
mNiStringExtraData.string = "MRK";
|
mNiStringExtraData.string = "MRK";
|
||||||
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
||||||
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -1069,10 +1069,10 @@ namespace
|
||||||
mNiStringExtraData.string = "MRK";
|
mNiStringExtraData.string = "MRK";
|
||||||
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
||||||
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
||||||
mNiTriShape.parent = &mNiNode2;
|
mNiTriShape.parents.push_back(&mNiNode2);
|
||||||
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
mNiNode2.recType = Nif::RC_RootCollisionNode;
|
mNiNode2.recType = Nif::RC_RootCollisionNode;
|
||||||
mNiNode2.parent = &mNiNode;
|
mNiNode2.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiNode2)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiNode2)}));
|
||||||
mNiNode.recType = Nif::RC_NiNode;
|
mNiNode.recType = Nif::RC_NiNode;
|
||||||
|
|
||||||
|
@ -1163,7 +1163,7 @@ 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.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
mNiNode.recType = Nif::RC_AvoidNode;
|
mNiNode.recType = Nif::RC_AvoidNode;
|
||||||
mNiTriStripsData.strips.front() = {0, 1};
|
mNiTriStripsData.strips.front() = {0, 1};
|
||||||
|
@ -1181,7 +1181,7 @@ 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.strips.front() = {0, 1};
|
mNiTriStripsData.strips.front() = {0, 1};
|
||||||
mNiTriStrips.parent = &mNiNode;
|
mNiTriStrips.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriStrips)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriStrips)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -1197,7 +1197,7 @@ 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.strips.front() = {0, 1};
|
mNiTriStripsData.strips.front() = {0, 1};
|
||||||
mNiTriShape.parent = &mNiNode;
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
||||||
|
@ -1218,4 +1218,54 @@ namespace
|
||||||
|
|
||||||
EXPECT_EQ(*result, expected);
|
EXPECT_EQ(*result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TestBulletNifLoader, should_handle_node_with_multiple_parents)
|
||||||
|
{
|
||||||
|
copy(mTransform, mNiTriShape.trafo);
|
||||||
|
mNiTriShape.trafo.scale = 4;
|
||||||
|
mNiTriShape.parents = {&mNiNode, &mNiNode2};
|
||||||
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
mNiNode.trafo.scale = 2;
|
||||||
|
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
mNiNode2.trafo.scale = 3;
|
||||||
|
|
||||||
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
|
||||||
|
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
||||||
|
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiNode2));
|
||||||
|
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
|
||||||
|
const auto result = mLoader.load(mNifFile);
|
||||||
|
|
||||||
|
std::unique_ptr<btTriangleMesh> triangles1(new btTriangleMesh(false));
|
||||||
|
triangles1->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
std::unique_ptr<Resource::TriangleMeshShape> mesh1(new Resource::TriangleMeshShape(triangles1.release(), true));
|
||||||
|
mesh1->setLocalScaling(btVector3(8, 8, 8));
|
||||||
|
std::unique_ptr<btTriangleMesh> triangles2(new btTriangleMesh(false));
|
||||||
|
triangles2->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
std::unique_ptr<Resource::TriangleMeshShape> mesh2(new Resource::TriangleMeshShape(triangles2.release(), true));
|
||||||
|
mesh2->setLocalScaling(btVector3(12, 12, 12));
|
||||||
|
std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
|
||||||
|
const btTransform transform1 {
|
||||||
|
btMatrix3x3(
|
||||||
|
1, 0, 0,
|
||||||
|
0, 0.8004512795493964327775415767973754555, 0.59939782204119995689950428641168400645,
|
||||||
|
0, -0.59939782204119995689950428641168400645, 0.8004512795493964327775415767973754555
|
||||||
|
),
|
||||||
|
btVector3(2, 4, 6)
|
||||||
|
};
|
||||||
|
const btTransform transform2 {
|
||||||
|
btMatrix3x3(
|
||||||
|
1, 0, 0,
|
||||||
|
0, 0.79515431915808965079861536651151254773, 0.60640713116208888600056070572463795543,
|
||||||
|
0, -0.60640713116208888600056070572463795543, 0.79515431915808965079861536651151254773
|
||||||
|
),
|
||||||
|
btVector3(3, 6, 9)
|
||||||
|
};
|
||||||
|
shape->addChildShape(transform1, mesh1.release());
|
||||||
|
shape->addChildShape(transform2, mesh2.release());
|
||||||
|
Resource::BulletShape expected;
|
||||||
|
expected.mCollisionShape.reset(shape.release());
|
||||||
|
expected.mAnimatedShapes = {{-1, 0}};
|
||||||
|
|
||||||
|
EXPECT_EQ(*result, expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ struct Node : public Named
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0))
|
if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0))
|
||||||
collision.read(nif);
|
collision.read(nif);
|
||||||
|
|
||||||
parent = nullptr;
|
parents.clear();
|
||||||
|
|
||||||
isBone = false;
|
isBone = false;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ struct Node : public Named
|
||||||
|
|
||||||
// Parent node, or nullptr for the root node. As far as I'm aware, only
|
// Parent node, or nullptr for the root node. As far as I'm aware, only
|
||||||
// NiNodes (or types derived from NiNodes) can be parents.
|
// NiNodes (or types derived from NiNodes) can be parents.
|
||||||
NiNode *parent;
|
std::vector<NiNode*> parents;
|
||||||
|
|
||||||
bool isBone{false};
|
bool isBone{false};
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ struct NiNode : Node
|
||||||
{
|
{
|
||||||
// Why would a unique list of children contain empty refs?
|
// Why would a unique list of children contain empty refs?
|
||||||
if(!children[i].empty())
|
if(!children[i].empty())
|
||||||
children[i]->parent = this;
|
children[i]->parents.push_back(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
15
components/nif/parent.hpp
Normal file
15
components/nif/parent.hpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_NIF_PARENT_HPP
|
||||||
|
#define OPENMW_COMPONENTS_NIF_PARENT_HPP
|
||||||
|
|
||||||
|
namespace Nif
|
||||||
|
{
|
||||||
|
struct NiNode;
|
||||||
|
|
||||||
|
struct Parent
|
||||||
|
{
|
||||||
|
const NiNode& mNiNode;
|
||||||
|
const Parent* mParent;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -16,15 +16,17 @@
|
||||||
#include <components/nif/node.hpp>
|
#include <components/nif/node.hpp>
|
||||||
#include <components/nif/data.hpp>
|
#include <components/nif/data.hpp>
|
||||||
#include <components/nif/extra.hpp>
|
#include <components/nif/extra.hpp>
|
||||||
|
#include <components/nif/parent.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
osg::Matrixf getWorldTransform(const Nif::Node& node)
|
osg::Matrixf getWorldTransform(const Nif::Node& node, const Nif::Parent* nodeParent)
|
||||||
{
|
{
|
||||||
if(node.parent != nullptr)
|
osg::Matrixf result = node.trafo.toMatrix();
|
||||||
return node.trafo.toMatrix() * getWorldTransform(*node.parent);
|
for (const Nif::Parent* parent = nodeParent; parent != nullptr; parent = parent->mParent)
|
||||||
return node.trafo.toMatrix();
|
result *= parent->mNiNode.trafo.toMatrix();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pathFileNameStartsWithX(const std::string& path)
|
bool pathFileNameStartsWithX(const std::string& path)
|
||||||
|
@ -214,7 +216,7 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
||||||
for (const Nif::Node* node : roots)
|
for (const Nif::Node* node : roots)
|
||||||
{
|
{
|
||||||
bool autogenerated = hasAutoGeneratedCollision(*node);
|
bool autogenerated = hasAutoGeneratedCollision(*node);
|
||||||
handleNode(filename, *node, 0, autogenerated, isAnimated, autogenerated);
|
handleNode(filename, *node, nullptr, 0, autogenerated, isAnimated, autogenerated);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCompoundShape)
|
if (mCompoundShape)
|
||||||
|
@ -305,8 +307,8 @@ bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node& rootNode)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& node, int flags,
|
void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent,
|
||||||
bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid)
|
int flags, bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid)
|
||||||
{
|
{
|
||||||
// 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.flags & Nif::NiNode::Flag_ActiveCollision))
|
||||||
|
@ -361,7 +363,7 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& n
|
||||||
|| node.recType == Nif::RC_NiTriStrips
|
|| node.recType == Nif::RC_NiTriStrips
|
||||||
|| node.recType == Nif::RC_BSLODTriShape))
|
|| node.recType == Nif::RC_BSLODTriShape))
|
||||||
{
|
{
|
||||||
handleNiTriShape(node, flags, getWorldTransform(node), isAnimated, avoid);
|
handleNiTriShape(node, parent, flags, getWorldTransform(node, parent), isAnimated, avoid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,30 +371,31 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& n
|
||||||
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::NodeList &list = ninode->children;
|
||||||
|
const Nif::Parent currentParent {*ninode, parent};
|
||||||
for(size_t i = 0;i < list.length();i++)
|
for(size_t i = 0;i < list.length();i++)
|
||||||
{
|
{
|
||||||
if (list[i].empty())
|
if (list[i].empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(list[i].get().parent == &node);
|
assert(std::find(list[i]->parents.begin(), list[i]->parents.end(), ninode) != list[i]->parents.end());
|
||||||
handleNode(fileName, list[i].get(), flags, isCollisionNode, isAnimated, autogenerated, avoid);
|
handleNode(fileName, list[i].get(), ¤tParent, flags, isCollisionNode, isAnimated, autogenerated, avoid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletNifLoader::handleNiTriShape(const Nif::Node& nifNode, int flags, const osg::Matrixf &transform,
|
void BulletNifLoader::handleNiTriShape(const Nif::Node& nifNode, const Nif::Parent* parent, int flags,
|
||||||
bool isAnimated, bool avoid)
|
const osg::Matrixf &transform, bool isAnimated, bool avoid)
|
||||||
{
|
{
|
||||||
// If the object was marked "NCO" earlier, it shouldn't collide with
|
// If the object was marked "NCO" earlier, it shouldn't collide with
|
||||||
// anything. So don't do anything.
|
// anything. So don't do anything.
|
||||||
if ((flags & 0x800))
|
if ((flags & 0x800))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
handleNiTriShape(static_cast<const Nif::NiGeometry&>(nifNode), transform, isAnimated, avoid);
|
handleNiTriShape(static_cast<const Nif::NiGeometry&>(nifNode), parent, transform, isAnimated, avoid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletNifLoader::handleNiTriShape(const Nif::NiGeometry& niGeometry, const osg::Matrixf &transform,
|
void BulletNifLoader::handleNiTriShape(const Nif::NiGeometry& niGeometry, const Nif::Parent* nodeParent,
|
||||||
bool isAnimated, bool avoid)
|
const osg::Matrixf &transform, bool isAnimated, bool avoid)
|
||||||
{
|
{
|
||||||
if (niGeometry.data.empty() || niGeometry.data->vertices.empty())
|
if (niGeometry.data.empty() || niGeometry.data->vertices.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -413,8 +416,8 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiGeometry& niGeometry, const
|
||||||
childMesh.release();
|
childMesh.release();
|
||||||
|
|
||||||
float scale = niGeometry.trafo.scale;
|
float scale = niGeometry.trafo.scale;
|
||||||
for (const Nif::Node* parent = niGeometry.parent; parent != nullptr; parent = parent->parent)
|
for (const Nif::Parent* parent = nodeParent; parent != nullptr; parent = parent->mParent)
|
||||||
scale *= parent->trafo.scale;
|
scale *= parent->mNiNode.trafo.scale;
|
||||||
osg::Quat q = transform.getRotate();
|
osg::Quat q = transform.getRotate();
|
||||||
osg::Vec3f v = transform.getTrans();
|
osg::Vec3f v = transform.getTrans();
|
||||||
childShape->setLocalScaling(btVector3(scale, scale, scale));
|
childShape->setLocalScaling(btVector3(scale, scale, scale));
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace Nif
|
||||||
struct NiTriShape;
|
struct NiTriShape;
|
||||||
struct NiTriStrips;
|
struct NiTriStrips;
|
||||||
struct NiGeometry;
|
struct NiGeometry;
|
||||||
|
struct Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NifBullet
|
namespace NifBullet
|
||||||
|
@ -55,14 +56,16 @@ public:
|
||||||
private:
|
private:
|
||||||
bool findBoundingBox(const Nif::Node& node, const std::string& filename);
|
bool findBoundingBox(const Nif::Node& node, const std::string& filename);
|
||||||
|
|
||||||
void handleNode(const std::string& fileName, const Nif::Node& node, int flags, bool isCollisionNode,
|
void handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent, int flags,
|
||||||
bool isAnimated=false, bool autogenerated=false, bool avoid=false);
|
bool isCollisionNode, bool isAnimated=false, bool autogenerated=false, bool avoid=false);
|
||||||
|
|
||||||
bool hasAutoGeneratedCollision(const Nif::Node& rootNode);
|
bool hasAutoGeneratedCollision(const Nif::Node& rootNode);
|
||||||
|
|
||||||
void handleNiTriShape(const Nif::Node& nifNode, int flags, const osg::Matrixf& transform, bool isAnimated, bool avoid);
|
void handleNiTriShape(const Nif::Node& nifNode, const Nif::Parent* parent, int flags, const osg::Matrixf& transform,
|
||||||
|
bool isAnimated, bool avoid);
|
||||||
|
|
||||||
void handleNiTriShape(const Nif::NiGeometry& nifNode, const osg::Matrixf& transform, bool isAnimated, bool avoid);
|
void handleNiTriShape(const Nif::NiGeometry& nifNode, const Nif::Parent* parent, const osg::Matrixf& transform,
|
||||||
|
bool isAnimated, bool avoid);
|
||||||
|
|
||||||
std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mCompoundShape;
|
std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mCompoundShape;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/misc/osguservalues.hpp>
|
#include <components/misc/osguservalues.hpp>
|
||||||
|
#include <components/nif/parent.hpp>
|
||||||
|
|
||||||
// particle
|
// particle
|
||||||
#include <osgParticle/ParticleSystem>
|
#include <osgParticle/ParticleSystem>
|
||||||
|
@ -74,10 +75,10 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the node hierarchy above it.
|
// Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the node hierarchy above it.
|
||||||
void collectDrawableProperties(const Nif::Node* nifNode, std::vector<const Nif::Property*>& out)
|
void collectDrawableProperties(const Nif::Node* nifNode, const Nif::Parent* parent, std::vector<const Nif::Property*>& out)
|
||||||
{
|
{
|
||||||
if (nifNode->parent)
|
if (parent != nullptr)
|
||||||
collectDrawableProperties(nifNode->parent, out);
|
collectDrawableProperties(&parent->mNiNode, parent->mParent, out);
|
||||||
const Nif::PropertyList& props = nifNode->props;
|
const Nif::PropertyList& props = nifNode->props;
|
||||||
for (size_t i = 0; i <props.length();++i)
|
for (size_t i = 0; i <props.length();++i)
|
||||||
{
|
{
|
||||||
|
@ -300,7 +301,7 @@ namespace NifOsg
|
||||||
created->setDataVariance(osg::Object::STATIC);
|
created->setDataVariance(osg::Object::STATIC);
|
||||||
for (const Nif::Node* root : roots)
|
for (const Nif::Node* root : roots)
|
||||||
{
|
{
|
||||||
auto node = handleNode(root, nullptr, imageManager, std::vector<unsigned int>(), 0, false, false, false, &textkeys->mTextKeys);
|
auto node = handleNode(root, nullptr, nullptr, imageManager, std::vector<unsigned int>(), 0, false, false, false, &textkeys->mTextKeys);
|
||||||
created->addChild(node);
|
created->addChild(node);
|
||||||
}
|
}
|
||||||
if (mHasNightDayLabel)
|
if (mHasNightDayLabel)
|
||||||
|
@ -339,7 +340,7 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
// 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->parent == nullptr && !mFoundFirstRootTexturingProperty && props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
if (nifNode->parents.empty() && !mFoundFirstRootTexturingProperty && props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
||||||
{
|
{
|
||||||
mFirstRootTextureIndex = props[i].getPtr()->recIndex;
|
mFirstRootTextureIndex = props[i].getPtr()->recIndex;
|
||||||
mFoundFirstRootTexturingProperty = true;
|
mFoundFirstRootTexturingProperty = true;
|
||||||
|
@ -483,7 +484,7 @@ namespace NifOsg
|
||||||
// The Root node can be created as a Group if no transformation is required.
|
// The Root node can be created as a Group if no transformation is required.
|
||||||
// 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 try).
|
// loaded from an external .kf file (original engine just throws "can't find node" errors if you try).
|
||||||
if (!nifNode->parent && nifNode->controller.empty() && nifNode->trafo.isIdentity())
|
if (nifNode->parents.empty() && nifNode->controller.empty() && nifNode->trafo.isIdentity())
|
||||||
node = new osg::Group;
|
node = new osg::Group;
|
||||||
|
|
||||||
dataVariance = nifNode->isBone ? osg::Object::DYNAMIC : osg::Object::STATIC;
|
dataVariance = nifNode->isBone ? osg::Object::DYNAMIC : osg::Object::STATIC;
|
||||||
|
@ -505,8 +506,10 @@ namespace NifOsg
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode,
|
||||||
std::vector<unsigned int> boundTextures, int animflags, bool skipMeshes, bool hasMarkers, bool hasAnimatedParents, SceneUtil::TextKeyMap* textKeys, osg::Node* rootNode=nullptr)
|
Resource::ImageManager* imageManager, std::vector<unsigned int> boundTextures, int animflags,
|
||||||
|
bool skipMeshes, bool hasMarkers, bool hasAnimatedParents, SceneUtil::TextKeyMap* textKeys,
|
||||||
|
osg::Node* rootNode=nullptr)
|
||||||
{
|
{
|
||||||
if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
|
if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -615,9 +618,9 @@ namespace NifOsg
|
||||||
Nif::NiSkinInstancePtr skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin;
|
Nif::NiSkinInstancePtr skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin;
|
||||||
|
|
||||||
if (skin.empty())
|
if (skin.empty())
|
||||||
handleGeometry(nifNode, node, composite, boundTextures, animflags);
|
handleGeometry(nifNode, parent, node, composite, boundTextures, animflags);
|
||||||
else
|
else
|
||||||
handleSkinnedGeometry(nifNode, node, composite, boundTextures, animflags);
|
handleSkinnedGeometry(nifNode, parent, node, composite, boundTextures, animflags);
|
||||||
|
|
||||||
if (!nifNode->controller.empty())
|
if (!nifNode->controller.empty())
|
||||||
handleMeshControllers(nifNode, node, composite, boundTextures, animflags);
|
handleMeshControllers(nifNode, node, composite, boundTextures, animflags);
|
||||||
|
@ -625,7 +628,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nifNode->recType == Nif::RC_NiParticles)
|
if (nifNode->recType == Nif::RC_NiParticles)
|
||||||
handleParticleSystem(nifNode, node, composite, animflags);
|
handleParticleSystem(nifNode, parent, node, composite, animflags);
|
||||||
|
|
||||||
if (composite->getNumControllers() > 0)
|
if (composite->getNumControllers() > 0)
|
||||||
{
|
{
|
||||||
|
@ -681,10 +684,11 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
const Nif::NodeList &children = ninode->children;
|
const Nif::NodeList &children = ninode->children;
|
||||||
|
const Nif::Parent currentParent {*ninode, parent};
|
||||||
for(size_t i = 0;i < children.length();++i)
|
for(size_t i = 0;i < children.length();++i)
|
||||||
{
|
{
|
||||||
if(!children[i].empty())
|
if(!children[i].empty())
|
||||||
handleNode(children[i].getPtr(), currentNode, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, hasAnimatedParents, textKeys, rootNode);
|
handleNode(children[i].getPtr(), ¤tParent, currentNode, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, hasAnimatedParents, textKeys, rootNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,7 +1030,8 @@ namespace NifOsg
|
||||||
mEmitterQueue.clear();
|
mEmitterQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
|
void handleParticleSystem(const Nif::Node *nifNode, const Nif::Parent* parent, osg::Group *parentNode,
|
||||||
|
SceneUtil::CompositeStateSetUpdater* composite, int animflags)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<ParticleSystem> partsys (new ParticleSystem);
|
osg::ref_ptr<ParticleSystem> partsys (new ParticleSystem);
|
||||||
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
||||||
|
@ -1095,7 +1100,7 @@ namespace NifOsg
|
||||||
handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf);
|
handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf);
|
||||||
|
|
||||||
std::vector<const Nif::Property*> drawableProps;
|
std::vector<const Nif::Property*> drawableProps;
|
||||||
collectDrawableProperties(nifNode, drawableProps);
|
collectDrawableProperties(nifNode, parent, drawableProps);
|
||||||
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
||||||
|
|
||||||
// particle system updater (after the emitters and affectors in the scene graph)
|
// particle system updater (after the emitters and affectors in the scene graph)
|
||||||
|
@ -1146,7 +1151,9 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleNiGeometry(const Nif::Node *nifNode, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
|
void handleNiGeometry(const Nif::Node *nifNode, const Nif::Parent* parent, osg::Geometry *geometry,
|
||||||
|
osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
||||||
|
const std::vector<unsigned int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
const Nif::NiGeometry* niGeometry = static_cast<const Nif::NiGeometry*>(nifNode);
|
const Nif::NiGeometry* niGeometry = static_cast<const Nif::NiGeometry*>(nifNode);
|
||||||
if (niGeometry->data.empty())
|
if (niGeometry->data.empty())
|
||||||
|
@ -1198,15 +1205,17 @@ namespace NifOsg
|
||||||
// - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them
|
// - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them
|
||||||
// above the actual renderable would be tedious.
|
// above the actual renderable would be tedious.
|
||||||
std::vector<const Nif::Property*> drawableProps;
|
std::vector<const Nif::Property*> drawableProps;
|
||||||
collectDrawableProperties(nifNode, drawableProps);
|
collectDrawableProperties(nifNode, parent, drawableProps);
|
||||||
applyDrawableProperties(parentNode, drawableProps, composite, !niGeometryData->colors.empty(), animflags);
|
applyDrawableProperties(parentNode, drawableProps, composite, !niGeometryData->colors.empty(), animflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleGeometry(const Nif::Node* nifNode, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
|
void handleGeometry(const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode,
|
||||||
|
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
|
||||||
|
int animflags)
|
||||||
{
|
{
|
||||||
assert(isTypeGeometry(nifNode->recType));
|
assert(isTypeGeometry(nifNode->recType));
|
||||||
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry);
|
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry);
|
||||||
handleNiGeometry(nifNode, geom, parentNode, composite, boundTextures, animflags);
|
handleNiGeometry(nifNode, parent, geom, parentNode, composite, boundTextures, animflags);
|
||||||
// If the record had no valid geometry data in it, early-out
|
// If the record had no valid geometry data in it, early-out
|
||||||
if (geom->empty())
|
if (geom->empty())
|
||||||
return;
|
return;
|
||||||
|
@ -1250,12 +1259,12 @@ namespace NifOsg
|
||||||
return morphGeom;
|
return morphGeom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSkinnedGeometry(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
void handleSkinnedGeometry(const Nif::Node *nifNode, const Nif::Parent* parent, osg::Group *parentNode,
|
||||||
const std::vector<unsigned int>& boundTextures, int animflags)
|
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
assert(isTypeGeometry(nifNode->recType));
|
assert(isTypeGeometry(nifNode->recType));
|
||||||
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||||
handleNiGeometry(nifNode, geometry, parentNode, composite, boundTextures, animflags);
|
handleNiGeometry(nifNode, parent, geometry, parentNode, composite, boundTextures, animflags);
|
||||||
if (geometry->empty())
|
if (geometry->empty())
|
||||||
return;
|
return;
|
||||||
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
||||||
|
|
Loading…
Reference in a new issue