mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
Merge branch 'ncc' into 'master'
#6496 Handle NCC flag in Nif files See merge request OpenMW/openmw!1516
This commit is contained in:
commit
c14796fc57
16 changed files with 114 additions and 38 deletions
|
@ -143,6 +143,7 @@
|
||||||
Feature #6380: Commas are treated as whitespace in vanilla
|
Feature #6380: Commas are treated as whitespace in vanilla
|
||||||
Feature #6419: Topics shouldn't be greyed out if they can produce another topic reference
|
Feature #6419: Topics shouldn't be greyed out if they can produce another topic reference
|
||||||
Feature #6443: Support NiStencilProperty
|
Feature #6443: Support NiStencilProperty
|
||||||
|
Feature #6496: NCC flag isn't handled properly
|
||||||
Feature #6534: Shader-based object texture blending
|
Feature #6534: Shader-based object texture blending
|
||||||
Feature #6541: Gloss-mapping
|
Feature #6541: Gloss-mapping
|
||||||
Feature #6592: Missing support for NiTriShape particle emitters
|
Feature #6592: Missing support for NiTriShape particle emitters
|
||||||
|
|
|
@ -54,7 +54,10 @@ namespace MWLua
|
||||||
{"HeightMap", MWPhysics::CollisionType_HeightMap},
|
{"HeightMap", MWPhysics::CollisionType_HeightMap},
|
||||||
{"Projectile", MWPhysics::CollisionType_Projectile},
|
{"Projectile", MWPhysics::CollisionType_Projectile},
|
||||||
{"Water", MWPhysics::CollisionType_Water},
|
{"Water", MWPhysics::CollisionType_Water},
|
||||||
{"Default", MWPhysics::CollisionType_Default}
|
{"Default", MWPhysics::CollisionType_Default},
|
||||||
|
{"AnyPhysical", MWPhysics::CollisionType_AnyPhysical},
|
||||||
|
{"Camera", MWPhysics::CollisionType_CameraOnly},
|
||||||
|
{"VisualOnly", MWPhysics::CollisionType_VisualOnly},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
api["castRay"] = [](const osg::Vec3f& from, const osg::Vec3f& to, sol::optional<sol::table> options)
|
api["castRay"] = [](const osg::Vec3f& from, const osg::Vec3f& to, sol::optional<sol::table> options)
|
||||||
|
|
|
@ -11,7 +11,10 @@ enum CollisionType {
|
||||||
CollisionType_HeightMap = 1<<3,
|
CollisionType_HeightMap = 1<<3,
|
||||||
CollisionType_Projectile = 1<<4,
|
CollisionType_Projectile = 1<<4,
|
||||||
CollisionType_Water = 1<<5,
|
CollisionType_Water = 1<<5,
|
||||||
CollisionType_Default = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door
|
CollisionType_Default = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door,
|
||||||
|
CollisionType_AnyPhysical = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door|CollisionType_Projectile|CollisionType_Water,
|
||||||
|
CollisionType_CameraOnly = 1<<6,
|
||||||
|
CollisionType_VisualOnly = 1<<7
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ namespace MWPhysics
|
||||||
btVector3 to = from - btVector3(0,0,maxHeight);
|
btVector3 to = from - btVector3(0,0,maxHeight);
|
||||||
|
|
||||||
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
||||||
resultCallback1.m_collisionFilterGroup = 0xff;
|
resultCallback1.m_collisionFilterGroup = CollisionType_AnyPhysical;
|
||||||
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap;
|
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap;
|
||||||
|
|
||||||
collisionWorld->rayTest(from, to, resultCallback1);
|
collisionWorld->rayTest(from, to, resultCallback1);
|
||||||
|
@ -426,7 +426,7 @@ namespace MWPhysics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ProjectileConvexCallback resultCallback(projectile.mCaster, projectile.mCollisionObject, btFrom, btTo, projectile.mProjectile);
|
ProjectileConvexCallback resultCallback(projectile.mCaster, projectile.mCollisionObject, btFrom, btTo, projectile.mProjectile);
|
||||||
resultCallback.m_collisionFilterMask = 0xff;
|
resultCallback.m_collisionFilterMask = CollisionType_AnyPhysical;
|
||||||
resultCallback.m_collisionFilterGroup = CollisionType_Projectile;
|
resultCallback.m_collisionFilterGroup = CollisionType_Projectile;
|
||||||
|
|
||||||
const btQuaternion btrot = btQuaternion::getIdentity();
|
const btQuaternion btrot = btQuaternion::getIdentity();
|
||||||
|
|
|
@ -661,7 +661,7 @@ namespace MWPhysics
|
||||||
btVector3 pos2 = Misc::Convert::toBullet(actor2->getCollisionObjectPosition() + osg::Vec3f(0,0,actor2->getHalfExtents().z() * 0.9));
|
btVector3 pos2 = Misc::Convert::toBullet(actor2->getCollisionObjectPosition() + osg::Vec3f(0,0,actor2->getHalfExtents().z() * 0.9));
|
||||||
|
|
||||||
btCollisionWorld::ClosestRayResultCallback resultCallback(pos1, pos2);
|
btCollisionWorld::ClosestRayResultCallback resultCallback(pos1, pos2);
|
||||||
resultCallback.m_collisionFilterGroup = 0xFF;
|
resultCallback.m_collisionFilterGroup = CollisionType_AnyPhysical;
|
||||||
resultCallback.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap|CollisionType_Door;
|
resultCallback.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap|CollisionType_Door;
|
||||||
|
|
||||||
MaybeLock lockColWorld(mCollisionWorldMutex, mNumThreads);
|
MaybeLock lockColWorld(mCollisionWorldMutex, mNumThreads);
|
||||||
|
|
|
@ -490,6 +490,17 @@ namespace MWPhysics
|
||||||
|
|
||||||
assert(!getObject(ptr));
|
assert(!getObject(ptr));
|
||||||
|
|
||||||
|
// Override collision type based on shape content.
|
||||||
|
switch (shapeInstance->mCollisionType)
|
||||||
|
{
|
||||||
|
case Resource::BulletShape::CollisionType::Camera:
|
||||||
|
collisionType = CollisionType_CameraOnly;
|
||||||
|
break;
|
||||||
|
case Resource::BulletShape::CollisionType::None:
|
||||||
|
collisionType = CollisionType_VisualOnly;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = std::make_shared<Object>(ptr, shapeInstance, rotation, collisionType, mTaskScheduler.get());
|
auto obj = std::make_shared<Object>(ptr, shapeInstance, rotation, collisionType, mTaskScheduler.get());
|
||||||
mObjects.emplace(ptr.mRef, obj);
|
mObjects.emplace(ptr.mRef, obj);
|
||||||
|
|
||||||
|
@ -905,7 +916,7 @@ namespace MWPhysics
|
||||||
const auto aabbMin = bulletPosition - btVector3(radius, radius, radius);
|
const auto aabbMin = bulletPosition - btVector3(radius, radius, radius);
|
||||||
const auto aabbMax = bulletPosition + btVector3(radius, radius, radius);
|
const auto aabbMax = bulletPosition + btVector3(radius, radius, radius);
|
||||||
const int mask = MWPhysics::CollisionType_Actor;
|
const int mask = MWPhysics::CollisionType_Actor;
|
||||||
const int group = 0xff;
|
const int group = MWPhysics::CollisionType_AnyPhysical;
|
||||||
if (occupyingActors == nullptr)
|
if (occupyingActors == nullptr)
|
||||||
{
|
{
|
||||||
HasSphereCollisionCallback callback(bulletPosition, radius, mask, group, ignoreFilter,
|
HasSphereCollisionCallback callback(bulletPosition, radius, mask, group, ignoreFilter,
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace MWRender
|
||||||
|
|
||||||
Camera::Camera (osg::Camera* camera)
|
Camera::Camera (osg::Camera* camera)
|
||||||
: mHeightScale(1.f),
|
: mHeightScale(1.f),
|
||||||
mCollisionType(MWPhysics::CollisionType::CollisionType_Default & ~MWPhysics::CollisionType::CollisionType_Actor),
|
mCollisionType((MWPhysics::CollisionType::CollisionType_Default & ~MWPhysics::CollisionType::CollisionType_Actor) | MWPhysics::CollisionType_CameraOnly),
|
||||||
mCamera(camera),
|
mCamera(camera),
|
||||||
mAnimation(nullptr),
|
mAnimation(nullptr),
|
||||||
mFirstPersonView(true),
|
mFirstPersonView(true),
|
||||||
|
|
|
@ -1009,9 +1009,9 @@ namespace
|
||||||
EXPECT_EQ(*result, expected);
|
EXPECT_EQ(*result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_extra_data_string_starting_with_nc_should_return_shape_with_null_collision_shape)
|
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_extra_data_string_equal_ncc_should_return_shape_with_cameraonly_collision)
|
||||||
{
|
{
|
||||||
mNiStringExtraData.string = "NC___";
|
mNiStringExtraData.string = "NCC__";
|
||||||
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
||||||
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
||||||
mNiTriShape.parents.push_back(&mNiNode);
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
|
@ -1022,12 +1022,16 @@ namespace
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
||||||
const auto result = mLoader.load(mNifFile);
|
const auto result = mLoader.load(mNifFile);
|
||||||
|
|
||||||
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
|
||||||
|
expected.mCollisionType = Resource::BulletShape::CollisionType::Camera;
|
||||||
|
|
||||||
EXPECT_EQ(*result, expected);
|
EXPECT_EQ(*result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_not_first_extra_data_string_starting_with_nc_should_return_shape_with_null_collision_shape)
|
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_not_first_extra_data_string_equal_ncc_should_return_shape_with_cameraonly_collision)
|
||||||
{
|
{
|
||||||
mNiStringExtraData.next = Nif::ExtraPtr(&mNiStringExtraData2);
|
mNiStringExtraData.next = Nif::ExtraPtr(&mNiStringExtraData2);
|
||||||
mNiStringExtraData2.string = "NC___";
|
mNiStringExtraData2.string = "NC___";
|
||||||
|
@ -1041,7 +1045,57 @@ namespace
|
||||||
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
||||||
const auto result = mLoader.load(mNifFile);
|
const auto result = mLoader.load(mNifFile);
|
||||||
|
|
||||||
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
Resource::BulletShape expected;
|
Resource::BulletShape expected;
|
||||||
|
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
|
||||||
|
expected.mCollisionType = Resource::BulletShape::CollisionType::Camera;
|
||||||
|
|
||||||
|
EXPECT_EQ(*result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_extra_data_string_starting_with_nc_should_return_shape_with_nocollision)
|
||||||
|
{
|
||||||
|
mNiStringExtraData.string = "NC___";
|
||||||
|
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
|
||||||
|
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
||||||
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
||||||
|
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
||||||
|
const auto result = mLoader.load(mNifFile);
|
||||||
|
|
||||||
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
Resource::BulletShape expected;
|
||||||
|
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
|
||||||
|
expected.mCollisionType = Resource::BulletShape::CollisionType::None;
|
||||||
|
|
||||||
|
EXPECT_EQ(*result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_not_first_extra_data_string_starting_with_nc_should_return_shape_with_nocollision)
|
||||||
|
{
|
||||||
|
mNiStringExtraData.next = Nif::ExtraPtr(&mNiStringExtraData2);
|
||||||
|
mNiStringExtraData2.string = "NC___";
|
||||||
|
mNiStringExtraData2.recType = Nif::RC_NiStringExtraData;
|
||||||
|
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
|
||||||
|
mNiTriShape.parents.push_back(&mNiNode);
|
||||||
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
|
||||||
|
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
|
||||||
|
const auto result = mLoader.load(mNifFile);
|
||||||
|
|
||||||
|
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
|
||||||
|
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
|
||||||
|
Resource::BulletShape expected;
|
||||||
|
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
|
||||||
|
expected.mCollisionType = Resource::BulletShape::CollisionType::None;
|
||||||
|
|
||||||
EXPECT_EQ(*result, expected);
|
EXPECT_EQ(*result, expected);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,10 @@ struct NiTextKeyExtraData : public Extra
|
||||||
|
|
||||||
struct NiStringExtraData : public Extra
|
struct NiStringExtraData : public Extra
|
||||||
{
|
{
|
||||||
/* Two known meanings:
|
/* Known meanings:
|
||||||
"MRK" - marker, only visible in the editor, not rendered in-game
|
"MRK" - marker, only visible in the editor, not rendered in-game
|
||||||
"NCO" - no collision
|
"NCC" - no collision except with the camera
|
||||||
|
Anything else starting with "NC" - no collision
|
||||||
*/
|
*/
|
||||||
std::string string;
|
std::string string;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include <components/nif/extra.hpp>
|
#include <components/nif/extra.hpp>
|
||||||
#include <components/nif/parent.hpp>
|
#include <components/nif/parent.hpp>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -215,7 +217,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, nullptr, 0, autogenerated, isAnimated, autogenerated);
|
handleNode(filename, *node, nullptr, 0, autogenerated, isAnimated, autogenerated, false, mShape->mCollisionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCompoundShape)
|
if (mCompoundShape)
|
||||||
|
@ -307,7 +309,7 @@ bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node& rootNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent,
|
void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& node, const Nif::Parent* parent,
|
||||||
int flags, bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid)
|
int flags, bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid, unsigned int& collisionType)
|
||||||
{
|
{
|
||||||
// TODO: allow on-the fly collision switching via toggling this flag
|
// TODO: allow on-the fly collision switching via toggling this flag
|
||||||
if (node.recType == Nif::RC_NiCollisionSwitch && !(node.flags & Nif::NiNode::Flag_ActiveCollision))
|
if (node.recType == Nif::RC_NiCollisionSwitch && !(node.flags & Nif::NiNode::Flag_ActiveCollision))
|
||||||
|
@ -341,8 +343,13 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& n
|
||||||
|
|
||||||
if (Misc::StringUtils::ciCompareLen(sd->string, "NC", 2) == 0)
|
if (Misc::StringUtils::ciCompareLen(sd->string, "NC", 2) == 0)
|
||||||
{
|
{
|
||||||
// No collision. Use an internal flag setting to mark this.
|
// NCC flag in vanilla is partly case sensitive: prefix NC is case insensitive but second C needs be uppercase
|
||||||
flags |= 0x800;
|
if (sd->string.length() > 2 && sd->string[2] == 'C')
|
||||||
|
// Collide only with camera.
|
||||||
|
collisionType = Resource::BulletShape::CollisionType::Camera;
|
||||||
|
else
|
||||||
|
// No collision.
|
||||||
|
collisionType = Resource::BulletShape::CollisionType::None;
|
||||||
}
|
}
|
||||||
else if (sd->string == "MRK" && autogenerated)
|
else if (sd->string == "MRK" && autogenerated)
|
||||||
{
|
{
|
||||||
|
@ -362,7 +369,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, parent, flags, getWorldTransform(node, parent), isAnimated, avoid);
|
handleNiTriShape(static_cast<const Nif::NiGeometry&>(node), parent, getWorldTransform(node, parent), isAnimated, avoid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,22 +384,11 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& n
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(std::find(list[i]->parents.begin(), list[i]->parents.end(), ninode) != list[i]->parents.end());
|
assert(std::find(list[i]->parents.begin(), list[i]->parents.end(), ninode) != list[i]->parents.end());
|
||||||
handleNode(fileName, list[i].get(), ¤tParent, flags, isCollisionNode, isAnimated, autogenerated, avoid);
|
handleNode(fileName, list[i].get(), ¤tParent, flags, isCollisionNode, isAnimated, autogenerated, avoid, collisionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletNifLoader::handleNiTriShape(const Nif::Node& nifNode, const Nif::Parent* parent, int flags,
|
|
||||||
const osg::Matrixf &transform, bool isAnimated, bool avoid)
|
|
||||||
{
|
|
||||||
// If the object was marked "NCO" earlier, it shouldn't collide with
|
|
||||||
// anything. So don't do anything.
|
|
||||||
if ((flags & 0x800))
|
|
||||||
return;
|
|
||||||
|
|
||||||
handleNiTriShape(static_cast<const Nif::NiGeometry&>(nifNode), parent, transform, isAnimated, avoid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BulletNifLoader::handleNiTriShape(const Nif::NiGeometry& niGeometry, const Nif::Parent* nodeParent,
|
void BulletNifLoader::handleNiTriShape(const Nif::NiGeometry& niGeometry, const Nif::Parent* nodeParent,
|
||||||
const osg::Matrixf &transform, bool isAnimated, bool avoid)
|
const osg::Matrixf &transform, bool isAnimated, bool avoid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,14 +56,11 @@ 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, const Nif::Parent* parent, int flags,
|
void handleNode(const std::string& fileName, const Nif::Node& node,const Nif::Parent* parent, int flags,
|
||||||
bool isCollisionNode, bool isAnimated=false, bool autogenerated=false, bool avoid=false);
|
bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid, unsigned int& cameraOnlyCollision);
|
||||||
|
|
||||||
bool hasAutoGeneratedCollision(const Nif::Node& rootNode);
|
bool hasAutoGeneratedCollision(const Nif::Node& rootNode);
|
||||||
|
|
||||||
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 Nif::Parent* parent, const osg::Matrixf& transform,
|
void handleNiTriShape(const Nif::NiGeometry& nifNode, const Nif::Parent* parent, const osg::Matrixf& transform,
|
||||||
bool isAnimated, bool avoid);
|
bool isAnimated, bool avoid);
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ BulletShapeInstance::BulletShapeInstance(osg::ref_ptr<const BulletShape> source)
|
||||||
{
|
{
|
||||||
mCollisionBox = mSource->mCollisionBox;
|
mCollisionBox = mSource->mCollisionBox;
|
||||||
mAnimatedShapes = mSource->mAnimatedShapes;
|
mAnimatedShapes = mSource->mAnimatedShapes;
|
||||||
|
mCollisionType = mSource->mCollisionType;
|
||||||
mCollisionShape = duplicateCollisionShape(mSource->mCollisionShape.get());
|
mCollisionShape = duplicateCollisionShape(mSource->mCollisionShape.get());
|
||||||
mAvoidCollisionShape = duplicateCollisionShape(mSource->mAvoidCollisionShape.get());
|
mAvoidCollisionShape = duplicateCollisionShape(mSource->mAvoidCollisionShape.get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,13 @@ namespace Resource
|
||||||
void setLocalScaling(const btVector3& scale);
|
void setLocalScaling(const btVector3& scale);
|
||||||
|
|
||||||
bool isAnimated() const { return !mAnimatedShapes.empty(); }
|
bool isAnimated() const { return !mAnimatedShapes.empty(); }
|
||||||
|
|
||||||
|
unsigned int mCollisionType = 0;
|
||||||
|
enum CollisionType
|
||||||
|
{
|
||||||
|
None = 0x1,
|
||||||
|
Camera = 0x2
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ local noHeadBobbing = 0
|
||||||
local noZoom = 0
|
local noZoom = 0
|
||||||
|
|
||||||
local function init()
|
local function init()
|
||||||
camera.setCollisionType(util.bitAnd(nearby.COLLISION_TYPE.Default, util.bitNot(nearby.COLLISION_TYPE.Actor)))
|
camera.setCollisionType(util.bitOr(util.bitAnd(nearby.COLLISION_TYPE.Default, util.bitNot(nearby.COLLISION_TYPE.Actor)), nearby.COLLISION_TYPE.Camera))
|
||||||
camera.setFieldOfView(camera.getBaseFieldOfView())
|
camera.setFieldOfView(camera.getBaseFieldOfView())
|
||||||
camera.allowCharacterDeferredRotation(settings._getBoolFromSettingsCfg('Camera', 'deferred preview rotation'))
|
camera.allowCharacterDeferredRotation(settings._getBoolFromSettingsCfg('Camera', 'deferred preview rotation'))
|
||||||
if camera.getMode() == MODE.FirstPerson then
|
if camera.getMode() == MODE.FirstPerson then
|
||||||
|
|
|
@ -28,10 +28,9 @@ local combatOffset = util.vector2(0, 15)
|
||||||
|
|
||||||
local state = defaultShoulder
|
local state = defaultShoulder
|
||||||
|
|
||||||
local rayOptions = {collisionType = nearby.COLLISION_TYPE.Default - nearby.COLLISION_TYPE.Actor}
|
|
||||||
local function ray(from, angle, limit)
|
local function ray(from, angle, limit)
|
||||||
local to = from + util.transform.rotateZ(angle) * util.vector3(0, limit, 0)
|
local to = from + util.transform.rotateZ(angle) * util.vector3(0, limit, 0)
|
||||||
local res = nearby.castRay(from, to, rayOptions)
|
local res = nearby.castRay(from, to, {collisionType = camera.getCollisionType()})
|
||||||
if res.hit then
|
if res.hit then
|
||||||
return (res.hitPos - from):length()
|
return (res.hitPos - from):length()
|
||||||
else
|
else
|
||||||
|
|
|
@ -34,7 +34,10 @@
|
||||||
-- @field [parent=#COLLISION_TYPE] #number HeightMap
|
-- @field [parent=#COLLISION_TYPE] #number HeightMap
|
||||||
-- @field [parent=#COLLISION_TYPE] #number Projectile
|
-- @field [parent=#COLLISION_TYPE] #number Projectile
|
||||||
-- @field [parent=#COLLISION_TYPE] #number Water
|
-- @field [parent=#COLLISION_TYPE] #number Water
|
||||||
-- @field [parent=#COLLISION_TYPE] #number Default Used by deafult: World+Door+Actor+HeightMap
|
-- @field [parent=#COLLISION_TYPE] #number Default Used by default: World+Door+Actor+HeightMap
|
||||||
|
-- @field [parent=#COLLISION_TYPE] #number AnyPhysical : World+Door+Actor+HeightMap+Projectile+Water
|
||||||
|
-- @field [parent=#COLLISION_TYPE] #number Camera Objects that should collide only with camera
|
||||||
|
-- @field [parent=#COLLISION_TYPE] #number VisualOnly Objects that were not intended to be part of the physics world
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Collision types that are used in `castRay`.
|
-- Collision types that are used in `castRay`.
|
||||||
|
|
Loading…
Reference in a new issue