1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-28 19:21:04 +00:00

Merge branch 'jamescameronsnif' into 'master'

NiPiñaColada and friends

See merge request OpenMW/openmw!1739
This commit is contained in:
psi29a 2022-04-05 11:53:20 +00:00
commit 3a21915bbd
4 changed files with 67 additions and 39 deletions

View File

@ -34,11 +34,12 @@ namespace Nif
mipmap = nif->getUInt(); mipmap = nif->getUInt();
alpha = nif->getUInt(); alpha = nif->getUInt();
nif->getChar(); // always 1 // Renderer hints, typically of no use for us
/* bool mIsStatic = */nif->getChar();
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,103)) if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,103))
nif->getBoolean(); // Direct rendering /* bool mDirectRendering = */nif->getBoolean();
if (nif->getVersion() >= NIFStream::generateVersion(20,2,0,4)) if (nif->getVersion() >= NIFStream::generateVersion(20,2,0,4))
nif->getBoolean(); // NiPersistentSrcTextureRendererData is used instead of NiPixelData /* bool mPersistRenderData = */nif->getBoolean();
} }
void NiSourceTexture::post(NIFFile *nif) void NiSourceTexture::post(NIFFile *nif)
@ -99,11 +100,11 @@ namespace Nif
NiParticleModifier::read(nif); NiParticleModifier::read(nif);
mBounceFactor = nif->getFloat(); mBounceFactor = nif->getFloat();
if (nif->getVersion() >= NIFStream::generateVersion(4,2,2,0)) if (nif->getVersion() >= NIFStream::generateVersion(4,2,0,2))
{ {
// Unused in NifSkope. Need to figure out what these do. // Unused in NifSkope. Need to figure out what these do.
/*bool spawnOnCollision = */nif->getBoolean(); /*bool mSpawnOnCollision = */nif->getBoolean();
/*bool dieOnCollision = */nif->getBoolean(); /*bool mDieOnCollision = */nif->getBoolean();
} }
} }
@ -111,11 +112,10 @@ namespace Nif
{ {
NiParticleCollider::read(nif); NiParticleCollider::read(nif);
/*unknown*/nif->getFloat(); mExtents = nif->getVector2();
mPosition = nif->getVector3();
for (int i=0;i<10;++i) mXVector = nif->getVector3();
/*unknown*/nif->getFloat(); mYVector = nif->getVector3();
mPlaneNormal = nif->getVector3(); mPlaneNormal = nif->getVector3();
mPlaneDistance = nif->getFloat(); mPlaneDistance = nif->getFloat();
} }
@ -124,12 +124,9 @@ namespace Nif
{ {
NiParticleModifier::read(nif); NiParticleModifier::read(nif);
/* /* bool mRandomInitialAxis = */nif->getChar();
byte (0 or 1) /* osg::Vec3f mInitialAxis = */nif->getVector3();
float (1) /* float mRotationSpeed = */nif->getFloat();
float*3
*/
nif->skip(17);
} }
void NiSphericalCollider::read(NIFStream* nif) void NiSphericalCollider::read(NIFStream* nif)

View File

@ -131,10 +131,13 @@ struct NiParticleCollider : public NiParticleModifier
// NiPinaColada // NiPinaColada
struct NiPlanarCollider : public NiParticleCollider struct NiPlanarCollider : public NiParticleCollider
{ {
void read(NIFStream *nif) override; osg::Vec2f mExtents;
osg::Vec3f mPosition;
osg::Vec3f mXVector, mYVector;
osg::Vec3f mPlaneNormal; osg::Vec3f mPlaneNormal;
float mPlaneDistance; float mPlaneDistance;
void read(NIFStream *nif) override;
}; };
struct NiSphericalCollider : public NiParticleCollider struct NiSphericalCollider : public NiParticleCollider

View File

@ -468,18 +468,24 @@ void FindGroupByRecIndex::applyNode(osg::Node &searchNode)
PlanarCollider::PlanarCollider(const Nif::NiPlanarCollider *collider) PlanarCollider::PlanarCollider(const Nif::NiPlanarCollider *collider)
: mBounceFactor(collider->mBounceFactor) : mBounceFactor(collider->mBounceFactor)
, mExtents(collider->mExtents)
, mPosition(collider->mPosition)
, mXVector(collider->mXVector)
, mYVector(collider->mYVector)
, mPlane(-collider->mPlaneNormal, collider->mPlaneDistance) , mPlane(-collider->mPlaneNormal, collider->mPlaneDistance)
{ {
} }
PlanarCollider::PlanarCollider()
: mBounceFactor(0.f)
{
}
PlanarCollider::PlanarCollider(const PlanarCollider &copy, const osg::CopyOp &copyop) PlanarCollider::PlanarCollider(const PlanarCollider &copy, const osg::CopyOp &copyop)
: osgParticle::Operator(copy, copyop) : osgParticle::Operator(copy, copyop)
, mBounceFactor(copy.mBounceFactor) , mBounceFactor(copy.mBounceFactor)
, mExtents(copy.mExtents)
, mPosition(copy.mPosition)
, mPositionInParticleSpace(copy.mPositionInParticleSpace)
, mXVector(copy.mXVector)
, mXVectorInParticleSpace(copy.mXVectorInParticleSpace)
, mYVector(copy.mYVector)
, mYVectorInParticleSpace(copy.mYVectorInParticleSpace)
, mPlane(copy.mPlane) , mPlane(copy.mPlane)
, mPlaneInParticleSpace(copy.mPlaneInParticleSpace) , mPlaneInParticleSpace(copy.mPlaneInParticleSpace)
{ {
@ -487,25 +493,44 @@ PlanarCollider::PlanarCollider(const PlanarCollider &copy, const osg::CopyOp &co
void PlanarCollider::beginOperate(osgParticle::Program *program) void PlanarCollider::beginOperate(osgParticle::Program *program)
{ {
mPositionInParticleSpace = mPosition;
mPlaneInParticleSpace = mPlane; mPlaneInParticleSpace = mPlane;
mXVectorInParticleSpace = mXVector;
mYVectorInParticleSpace = mYVector;
if (program->getReferenceFrame() == osgParticle::ParticleProcessor::ABSOLUTE_RF) if (program->getReferenceFrame() == osgParticle::ParticleProcessor::ABSOLUTE_RF)
{
mPositionInParticleSpace = program->transformLocalToWorld(mPosition);
mPlaneInParticleSpace.transform(program->getLocalToWorldMatrix()); mPlaneInParticleSpace.transform(program->getLocalToWorldMatrix());
mXVectorInParticleSpace = program->rotateLocalToWorld(mXVector);
mYVectorInParticleSpace = program->rotateLocalToWorld(mYVector);
}
} }
void PlanarCollider::operate(osgParticle::Particle *particle, double dt) void PlanarCollider::operate(osgParticle::Particle *particle, double dt)
{ {
float dotproduct = particle->getVelocity() * mPlaneInParticleSpace.getNormal(); // Does the particle in question move towards the collider?
float velDotProduct = particle->getVelocity() * mPlaneInParticleSpace.getNormal();
if (velDotProduct <= 0)
return;
if (dotproduct > 0) // Does it intersect the collider's plane?
{ osg::BoundingSphere bs(particle->getPosition(), 0.f);
osg::BoundingSphere bs(particle->getPosition(), 0.f); if (mPlaneInParticleSpace.intersect(bs) != 1)
if (mPlaneInParticleSpace.intersect(bs) == 1) return;
{
osg::Vec3 reflectedVelocity = particle->getVelocity() - mPlaneInParticleSpace.getNormal() * (2 * dotproduct); // Is it inside the collider's bounds?
reflectedVelocity *= mBounceFactor; osg::Vec3f relativePos = particle->getPosition() - mPositionInParticleSpace;
particle->setVelocity(reflectedVelocity); float xDotProduct = relativePos * mXVectorInParticleSpace;
} float yDotProduct = relativePos * mYVectorInParticleSpace;
} if (-mExtents.x() * 0.5f > xDotProduct || mExtents.x() * 0.5f < xDotProduct)
return;
if (-mExtents.y() * 0.5f > yDotProduct || mExtents.y() * 0.5f < yDotProduct)
return;
// Deflect the particle
osg::Vec3 reflectedVelocity = particle->getVelocity() - mPlaneInParticleSpace.getNormal() * (2 * velDotProduct);
reflectedVelocity *= mBounceFactor;
particle->setVelocity(reflectedVelocity);
} }
SphericalCollider::SphericalCollider(const Nif::NiSphericalCollider* collider) SphericalCollider::SphericalCollider(const Nif::NiSphericalCollider* collider)

View File

@ -104,7 +104,7 @@ namespace NifOsg
{ {
public: public:
PlanarCollider(const Nif::NiPlanarCollider* collider); PlanarCollider(const Nif::NiPlanarCollider* collider);
PlanarCollider(); PlanarCollider() = default;
PlanarCollider(const PlanarCollider& copy, const osg::CopyOp& copyop); PlanarCollider(const PlanarCollider& copy, const osg::CopyOp& copyop);
META_Object(NifOsg, PlanarCollider) META_Object(NifOsg, PlanarCollider)
@ -113,9 +113,12 @@ namespace NifOsg
void operate(osgParticle::Particle* particle, double dt) override; void operate(osgParticle::Particle* particle, double dt) override;
private: private:
float mBounceFactor; float mBounceFactor{0.f};
osg::Plane mPlane; osg::Vec2f mExtents;
osg::Plane mPlaneInParticleSpace; osg::Vec3f mPosition, mPositionInParticleSpace;
osg::Vec3f mXVector, mXVectorInParticleSpace;
osg::Vec3f mYVector, mYVectorInParticleSpace;
osg::Plane mPlane, mPlaneInParticleSpace;
}; };
class SphericalCollider : public osgParticle::Operator class SphericalCollider : public osgParticle::Operator