mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-09 21:44:54 +00:00
Handle NCC flag in Nif files. Objects with this flag will collide only with camera.
Expose objects with NC flag to be used by Lua mods.
This commit is contained in:
parent
68799cfd2b
commit
d05a2facf3
@ -140,6 +140,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…
x
Reference in New Issue
Block a user