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

Merge branch 'nif' into 'master'

Modernize NIF loader, part 1

See merge request OpenMW/openmw!3394
This commit is contained in:
psi29a 2023-09-03 10:34:46 +00:00
commit ccc465db27
No known key found for this signature in database
24 changed files with 808 additions and 818 deletions

View File

@ -13,7 +13,7 @@ namespace Nif::Testing
inline void init(Extra& value)
{
value.next = ExtraPtr(nullptr);
value.mNext = ExtraPtr(nullptr);
}
inline void init(Named& value)

View File

@ -996,7 +996,7 @@ namespace
TEST_F(TestBulletNifLoader,
for_tri_shape_child_node_with_extra_data_string_equal_ncc_should_return_shape_with_cameraonly_collision)
{
mNiStringExtraData.string = "NCC__";
mNiStringExtraData.mData = "NCC__";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode);
@ -1024,8 +1024,8 @@ namespace
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);
mNiStringExtraData2.string = "NCC__";
mNiStringExtraData.mNext = Nif::ExtraPtr(&mNiStringExtraData2);
mNiStringExtraData2.mData = "NCC__";
mNiStringExtraData2.recType = Nif::RC_NiStringExtraData;
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode);
@ -1052,7 +1052,7 @@ namespace
TEST_F(TestBulletNifLoader,
for_tri_shape_child_node_with_extra_data_string_starting_with_nc_should_return_shape_with_nocollision)
{
mNiStringExtraData.string = "NC___";
mNiStringExtraData.mData = "NC___";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode);
@ -1079,8 +1079,8 @@ namespace
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___";
mNiStringExtraData.mNext = Nif::ExtraPtr(&mNiStringExtraData2);
mNiStringExtraData2.mData = "NC___";
mNiStringExtraData2.recType = Nif::RC_NiStringExtraData;
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode);
@ -1141,7 +1141,7 @@ namespace
TEST_F(TestBulletNifLoader,
for_tri_shape_child_node_with_extra_data_string_mrk_should_return_shape_with_null_collision_shape)
{
mNiStringExtraData.string = "MRK";
mNiStringExtraData.mData = "MRK";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode);
@ -1160,7 +1160,7 @@ namespace
TEST_F(TestBulletNifLoader, bsx_editor_marker_flag_disables_collision_for_markers)
{
mNiIntegerExtraData.data = 32; // BSX flag "editor marker"
mNiIntegerExtraData.mData = 32; // BSX flag "editor marker"
mNiIntegerExtraData.recType = Nif::RC_BSXFlags;
mNiTriShape.extralist.push_back(Nif::ExtraPtr(&mNiIntegerExtraData));
mNiTriShape.parents.push_back(&mNiNode);
@ -1181,7 +1181,7 @@ namespace
TEST_F(TestBulletNifLoader,
for_tri_shape_child_node_with_extra_data_string_mrk_and_other_collision_node_should_return_shape_with_triangle_mesh_shape_with_all_meshes)
{
mNiStringExtraData.string = "MRK";
mNiStringExtraData.mData = "MRK";
mNiStringExtraData.recType = Nif::RC_NiStringExtraData;
mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData);
mNiTriShape.parents.push_back(&mNiNode2);

View File

@ -111,7 +111,7 @@ add_component_dir (sceneutil
)
add_component_dir (nif
controlled effect niftypes record controller extra node record_ptr data niffile property nifkey base nifstream physics
base controller data effect extra niffile nifkey nifstream niftypes node particle physics property record record_ptr texture
)
add_component_dir (nifosg

View File

@ -5,11 +5,11 @@ namespace Nif
void Extra::read(NIFStream* nif)
{
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0))
name = nif->getString();
nif->read(mName);
else if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
{
next.read(nif);
recordSize = nif->getUInt();
mNext.read(nif);
nif->read(mRecordSize);
}
}

View File

@ -13,12 +13,12 @@ namespace Nif
// An extra data record. All the extra data connected to an object form a linked list.
struct Extra : public Record
{
std::string name;
ExtraPtr next; // Next extra data record in the list
unsigned int recordSize{ 0u };
std::string mName;
ExtraPtr mNext; // Next extra data record in the list
uint32_t mRecordSize{ 0u };
void read(NIFStream* nif) override;
void post(Reader& nif) override { next.post(nif); }
void post(Reader& nif) override { mNext.post(nif); }
};
struct Controller : public Record

View File

@ -1,140 +0,0 @@
#include "controlled.hpp"
#include "data.hpp"
namespace Nif
{
void NiSourceTexture::read(NIFStream* nif)
{
Named::read(nif);
external = nif->getChar() != 0;
bool internal = false;
if (external)
filename = nif->getString();
else
{
if (nif->getVersion() <= NIFStream::generateVersion(10, 0, 1, 3))
internal = nif->getChar();
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
filename = nif->getString(); // Original file path of the internal texture
}
if (nif->getVersion() <= NIFStream::generateVersion(10, 0, 1, 3))
{
if (!external && internal)
data.read(nif);
}
else
{
data.read(nif);
}
pixel = nif->getUInt();
mipmap = nif->getUInt();
alpha = nif->getUInt();
// Renderer hints, typically of no use for us
/* bool mIsStatic = */ nif->getChar();
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 103))
/* bool mDirectRendering = */ nif->getBoolean();
if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 4))
/* bool mPersistRenderData = */ nif->getBoolean();
}
void NiSourceTexture::post(Reader& nif)
{
Named::post(nif);
data.post(nif);
}
void BSShaderTextureSet::read(NIFStream* nif)
{
nif->getSizedStrings(textures, nif->getUInt());
}
void NiParticleModifier::read(NIFStream* nif)
{
next.read(nif);
controller.read(nif);
}
void NiParticleModifier::post(Reader& nif)
{
next.post(nif);
controller.post(nif);
}
void NiParticleGrowFade::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
growTime = nif->getFloat();
fadeTime = nif->getFloat();
}
void NiParticleColorModifier::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
data.read(nif);
}
void NiParticleColorModifier::post(Reader& nif)
{
NiParticleModifier::post(nif);
data.post(nif);
}
void NiGravity::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
mDecay = nif->getFloat();
mForce = nif->getFloat();
mType = nif->getUInt();
mPosition = nif->getVector3();
mDirection = nif->getVector3();
}
void NiParticleCollider::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
mBounceFactor = nif->getFloat();
if (nif->getVersion() >= NIFStream::generateVersion(4, 2, 0, 2))
{
// Unused in NifSkope. Need to figure out what these do.
/*bool mSpawnOnCollision = */ nif->getBoolean();
/*bool mDieOnCollision = */ nif->getBoolean();
}
}
void NiPlanarCollider::read(NIFStream* nif)
{
NiParticleCollider::read(nif);
mExtents = nif->getVector2();
mPosition = nif->getVector3();
mXVector = nif->getVector3();
mYVector = nif->getVector3();
mPlaneNormal = nif->getVector3();
mPlaneDistance = nif->getFloat();
}
void NiParticleRotation::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
/* bool mRandomInitialAxis = */ nif->getChar();
/* osg::Vec3f mInitialAxis = */ nif->getVector3();
/* float mRotationSpeed = */ nif->getFloat();
}
void NiSphericalCollider::read(NIFStream* nif)
{
NiParticleCollider::read(nif);
mRadius = nif->getFloat();
mCenter = nif->getVector3();
}
}

View File

@ -1,157 +0,0 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: https://openmw.org/
This file (controlled.h) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
https://www.gnu.org/licenses/ .
*/
#ifndef OPENMW_COMPONENTS_NIF_CONTROLLED_HPP
#define OPENMW_COMPONENTS_NIF_CONTROLLED_HPP
#include "base.hpp"
namespace Nif
{
struct NiSourceTexture : public Named
{
// Is this an external (references a separate texture file) or
// internal (data is inside the nif itself) texture?
bool external;
std::string filename; // In case of external textures
NiPixelDataPtr data; // In case of internal textures
/* Pixel layout
0 - Palettised
1 - High color 16
2 - True color 32
3 - Compressed
4 - Bumpmap
5 - Default */
unsigned int pixel;
/* Mipmap format
0 - no
1 - yes
2 - default */
unsigned int mipmap;
/* Alpha
0 - none
1 - binary
2 - smooth
3 - default (use material alpha, or multiply material with texture if present)
*/
unsigned int alpha;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct BSShaderTextureSet : public Record
{
enum TextureType
{
TextureType_Base = 0,
TextureType_Normal = 1,
TextureType_Glow = 2,
TextureType_Parallax = 3,
TextureType_Env = 4,
TextureType_EnvMask = 5,
TextureType_Subsurface = 6,
TextureType_BackLighting = 7
};
std::vector<std::string> textures;
void read(NIFStream* nif) override;
};
struct NiParticleModifier : public Record
{
NiParticleModifierPtr next;
ControllerPtr controller;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct NiParticleGrowFade : public NiParticleModifier
{
float growTime;
float fadeTime;
void read(NIFStream* nif) override;
};
struct NiParticleColorModifier : public NiParticleModifier
{
NiColorDataPtr data;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct NiGravity : public NiParticleModifier
{
float mForce;
/* 0 - Wind (fixed direction)
* 1 - Point (fixed origin)
*/
int mType;
float mDecay;
osg::Vec3f mPosition;
osg::Vec3f mDirection;
void read(NIFStream* nif) override;
};
struct NiParticleCollider : public NiParticleModifier
{
float mBounceFactor;
void read(NIFStream* nif) override;
};
// NiPinaColada
struct NiPlanarCollider : public NiParticleCollider
{
osg::Vec2f mExtents;
osg::Vec3f mPosition;
osg::Vec3f mXVector, mYVector;
osg::Vec3f mPlaneNormal;
float mPlaneDistance;
void read(NIFStream* nif) override;
};
struct NiSphericalCollider : public NiParticleCollider
{
float mRadius;
osg::Vec3f mCenter;
void read(NIFStream* nif) override;
};
struct NiParticleRotation : public NiParticleModifier
{
void read(NIFStream* nif) override;
};
} // Namespace
#endif

View File

@ -1,9 +1,9 @@
#include "controller.hpp"
#include "controlled.hpp"
#include "data.hpp"
#include "node.hpp"
#include "recordptr.hpp"
#include "particle.hpp"
#include "texture.hpp"
namespace Nif
{

View File

@ -1,7 +1,7 @@
#include "effect.hpp"
#include "controlled.hpp"
#include "node.hpp"
#include "texture.hpp"
namespace Nif
{
@ -9,55 +9,61 @@ namespace Nif
void NiDynamicEffect::read(NIFStream* nif)
{
Node::read(nif);
if (nif->getVersion() >= nif->generateVersion(10, 1, 0, 106)
&& nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
nif->getBoolean(); // Switch state
if (nif->getVersion() <= NIFFile::VER_MW
|| (nif->getVersion() >= nif->generateVersion(10, 1, 0, 0)
&& nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4))
{
if (nif->getVersion() > NIFFile::VER_MW && nif->getVersion() < nif->generateVersion(10, 1, 0, 0))
return;
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4)
return;
if (nif->getVersion() >= nif->generateVersion(10, 1, 0, 106))
nif->read(mSwitchState);
size_t numAffectedNodes = nif->get<uint32_t>();
nif->skip(numAffectedNodes * 4);
}
}
void NiLight::read(NIFStream* nif)
{
NiDynamicEffect::read(nif);
dimmer = nif->getFloat();
ambient = nif->getVector3();
diffuse = nif->getVector3();
specular = nif->getVector3();
mDimmer = nif->getFloat();
mAmbient = nif->getVector3();
mDiffuse = nif->getVector3();
mSpecular = nif->getVector3();
}
void NiPointLight::read(NIFStream* nif)
{
NiLight::read(nif);
mConstantAttenuation = nif->getFloat();
mLinearAttenuation = nif->getFloat();
mQuadraticAttenuation = nif->getFloat();
}
void NiSpotLight::read(NIFStream* nif)
{
NiPointLight::read(nif);
mCutoff = nif->getFloat();
mExponent = nif->getFloat();
}
void NiTextureEffect::read(NIFStream* nif)
{
NiDynamicEffect::read(nif);
// Model Projection Matrix
nif->skip(3 * 3 * sizeof(float));
// Model Projection Transform
nif->skip(3 * sizeof(float));
// Texture Filtering
nif->skip(4);
// Max anisotropy samples
nif->read(mProjectionRotation);
nif->read(mProjectionPosition);
nif->read(mFilterMode);
if (nif->getVersion() >= NIFStream::generateVersion(20, 5, 0, 4))
nif->skip(2);
clamp = nif->getUInt();
textureType = (TextureType)nif->getUInt();
coordGenType = (CoordGenType)nif->getUInt();
texture.read(nif);
nif->skip(1); // Use clipping plane
nif->skip(16); // Clipping plane dimensions vector
nif->read(mMaxAnisotropy);
nif->read(mClampMode);
mTextureType = static_cast<TextureType>(nif->get<uint32_t>());
mCoordGenType = static_cast<CoordGenType>(nif->get<uint32_t>());
mTexture.read(nif);
nif->read(mEnableClipPlane);
mClipPlane = osg::Plane(nif->get<osg::Vec4f>());
if (nif->getVersion() <= NIFStream::generateVersion(10, 2, 0, 0))
nif->skip(4); // PS2-specific shorts
if (nif->getVersion() <= NIFStream::generateVersion(4, 1, 0, 12))
@ -67,24 +73,8 @@ namespace Nif
void NiTextureEffect::post(Reader& nif)
{
NiDynamicEffect::post(nif);
texture.post(nif);
}
void NiPointLight::read(NIFStream* nif)
{
NiLight::read(nif);
constantAttenuation = nif->getFloat();
linearAttenuation = nif->getFloat();
quadraticAttenuation = nif->getFloat();
}
void NiSpotLight::read(NIFStream* nif)
{
NiPointLight::read(nif);
cutoff = nif->getFloat();
exponent = nif->getFloat();
mTexture.post(nif);
}
}

View File

@ -29,67 +29,75 @@
namespace Nif
{
// Abstract
struct NiDynamicEffect : public Node
{
bool mSwitchState{ true };
void read(NIFStream* nif) override;
};
// Used as base for NiAmbientLight, NiDirectionalLight, NiPointLight and NiSpotLight.
// Abstract light source
struct NiLight : NiDynamicEffect
{
float dimmer;
osg::Vec3f ambient;
osg::Vec3f diffuse;
osg::Vec3f specular;
float mDimmer;
osg::Vec3f mAmbient;
osg::Vec3f mDiffuse;
osg::Vec3f mSpecular;
void read(NIFStream* nif) override;
};
struct NiPointLight : public NiLight
{
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
float mConstantAttenuation;
float mLinearAttenuation;
float mQuadraticAttenuation;
void read(NIFStream* nif) override;
};
struct NiSpotLight : public NiPointLight
{
float cutoff;
float exponent;
float mCutoff;
float mExponent;
void read(NIFStream* nif) override;
};
struct NiTextureEffect : NiDynamicEffect
{
NiSourceTexturePtr texture;
unsigned int clamp;
enum TextureType
enum class TextureType : uint32_t
{
Projected_Light = 0,
Projected_Shadow = 1,
Environment_Map = 2,
Fog_Map = 3
ProjectedLight = 0,
ProjectedShadow = 1,
EnvironmentMap = 2,
FogMap = 3,
};
TextureType textureType;
enum CoordGenType
enum class CoordGenType : uint32_t
{
World_Parallel = 0,
World_Perspective,
Sphere_Map,
Specular_Cube_Map,
Diffuse_Cube_Map
WorldParallel = 0,
WorldPerspective = 1,
SphereMap = 2,
SpecularCubeMap = 3,
DiffuseCubeMap = 4,
};
CoordGenType coordGenType;
Matrix3 mProjectionRotation;
osg::Vec3f mProjectionPosition;
uint32_t mFilterMode;
NiSourceTexturePtr mTexture;
uint16_t mMaxAnisotropy{ 0 };
uint32_t mClampMode;
TextureType mTextureType;
CoordGenType mCoordGenType;
uint8_t mEnableClipPlane;
osg::Plane mClipPlane;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
bool wrapT() const { return clamp & 1; }
bool wrapS() const { return (clamp >> 1) & 1; }
bool wrapT() const { return mClampMode & 1; }
bool wrapS() const { return mClampMode & 2; }
};
} // Namespace

View File

@ -6,25 +6,21 @@ namespace Nif
void NiExtraData::read(NIFStream* nif)
{
Extra::read(nif);
nif->readVector(data, recordSize);
}
void NiStringExtraData::read(NIFStream* nif)
{
Extra::read(nif);
string = nif->getString();
nif->readVector(mData, mRecordSize);
}
void NiTextKeyExtraData::read(NIFStream* nif)
{
Extra::read(nif);
int keynum = nif->getInt();
list.resize(keynum);
for (int i = 0; i < keynum; i++)
uint32_t numKeys;
nif->read(numKeys);
mList.resize(numKeys);
for (TextKey& key : mList)
{
list[i].time = nif->getFloat();
list[i].text = nif->getString();
nif->read(key.mTime);
nif->read(key.mText);
}
}
@ -32,81 +28,39 @@ namespace Nif
{
Extra::read(nif);
nif->skip(nif->getUShort() * sizeof(float)); // vertex weights I guess
}
void NiIntegerExtraData::read(NIFStream* nif)
{
Extra::read(nif);
data = nif->getUInt();
}
void NiIntegersExtraData::read(NIFStream* nif)
{
Extra::read(nif);
nif->readVector(data, nif->getUInt());
}
void NiBinaryExtraData::read(NIFStream* nif)
{
Extra::read(nif);
nif->readVector(data, nif->getUInt());
}
void NiBooleanExtraData::read(NIFStream* nif)
{
Extra::read(nif);
data = nif->getBoolean();
}
void NiVectorExtraData::read(NIFStream* nif)
{
Extra::read(nif);
data = nif->getVector4();
}
void NiFloatExtraData::read(NIFStream* nif)
{
Extra::read(nif);
data = nif->getFloat();
}
void NiFloatsExtraData::read(NIFStream* nif)
{
Extra::read(nif);
nif->readVector(data, nif->getUInt());
nif->skip(nif->get<uint16_t>() * sizeof(float)); // vertex weights I guess
}
void BSBound::read(NIFStream* nif)
{
Extra::read(nif);
center = nif->getVector3();
halfExtents = nif->getVector3();
nif->read(mCenter);
nif->read(mExtents);
}
void BSFurnitureMarker::LegacyFurniturePosition::read(NIFStream* nif)
{
mOffset = nif->getVector3();
mOrientation = nif->getUShort();
mPositionRef = nif->getChar();
nif->read(mOffset);
nif->read(mOrientation);
nif->read(mPositionRef);
nif->skip(1); // Position ref 2
}
void BSFurnitureMarker::FurniturePosition::read(NIFStream* nif)
{
mOffset = nif->getVector3();
mHeading = nif->getFloat();
mType = nif->getUShort();
mEntryPoint = nif->getUShort();
nif->read(mOffset);
nif->read(mHeading);
nif->read(mType);
nif->read(mEntryPoint);
}
void BSFurnitureMarker::read(NIFStream* nif)
{
Extra::read(nif);
unsigned int num = nif->getUInt();
uint32_t num;
nif->read(num);
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
{
mLegacyMarkers.resize(num);
@ -124,19 +78,20 @@ namespace Nif
void BSInvMarker::read(NIFStream* nif)
{
Extra::read(nif);
float rotX = nif->getUShort() / 1000.0;
float rotY = nif->getUShort() / 1000.0;
float rotZ = nif->getUShort() / 1000.0;
mScale = nif->getFloat();
float rotX = nif->get<uint16_t>() / 1000.f;
float rotY = nif->get<uint16_t>() / 1000.f;
float rotZ = nif->get<uint16_t>() / 1000.f;
mRotation = osg::Quat(rotX, osg::X_AXIS, rotY, osg::Y_AXIS, rotZ, osg::Z_AXIS);
nif->read(mScale);
}
void BSBehaviorGraphExtraData::read(NIFStream* nif)
{
Extra::read(nif);
mFile = nif->getString();
mControlsBaseSkeleton = nif->getBoolean();
nif->read(mFile);
nif->read(mControlsBaseSkeleton);
}
}

View File

@ -1,26 +1,3 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: https://openmw.org/
This file (extra.h) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
https://www.gnu.org/licenses/ .
*/
#ifndef OPENMW_COMPONENTS_NIF_EXTRA_HPP
#define OPENMW_COMPONENTS_NIF_EXTRA_HPP
@ -29,9 +6,46 @@
namespace Nif
{
template <typename T>
struct TypedExtra : public Extra
{
T mData;
void read(NIFStream* nif) override
{
Extra::read(nif);
nif->read(mData);
}
};
template <typename T>
struct TypedVectorExtra : public Extra
{
std::vector<T> mData;
void read(NIFStream* nif) override
{
Extra::read(nif);
nif->readVector(mData, nif->get<uint32_t>());
}
};
using NiBooleanExtraData = TypedExtra<bool>;
using NiFloatExtraData = TypedExtra<float>;
using NiIntegerExtraData = TypedExtra<uint32_t>;
using NiStringExtraData = TypedExtra<std::string>;
using NiVectorExtraData = TypedExtra<osg::Vec4f>;
using NiBinaryExtraData = TypedVectorExtra<uint8_t>;
using NiFloatsExtraData = TypedVectorExtra<float>;
using NiIntegersExtraData = TypedVectorExtra<uint32_t>;
// Distinct from NiBinaryExtraData, uses mRecordSize as its size
struct NiExtraData : public Extra
{
std::vector<char> data;
std::vector<uint8_t> mData;
void read(NIFStream* nif) override;
};
@ -45,78 +59,17 @@ namespace Nif
{
struct TextKey
{
float time;
std::string text;
float mTime;
std::string mText;
};
std::vector<TextKey> list;
void read(NIFStream* nif) override;
};
struct NiStringExtraData : public Extra
{
/* Known meanings:
"MRK" - marker, only visible in the editor, not rendered in-game
"NCC" - no collision except with the camera
Anything else starting with "NC" - no collision
*/
std::string string;
void read(NIFStream* nif) override;
};
struct NiIntegerExtraData : public Extra
{
unsigned int data;
void read(NIFStream* nif) override;
};
struct NiIntegersExtraData : public Extra
{
std::vector<unsigned int> data;
void read(NIFStream* nif) override;
};
struct NiBinaryExtraData : public Extra
{
std::vector<char> data;
void read(NIFStream* nif) override;
};
struct NiBooleanExtraData : public Extra
{
bool data;
void read(NIFStream* nif) override;
};
struct NiVectorExtraData : public Extra
{
osg::Vec4f data;
void read(NIFStream* nif) override;
};
struct NiFloatExtraData : public Extra
{
float data;
void read(NIFStream* nif) override;
};
struct NiFloatsExtraData : public Extra
{
std::vector<float> data;
std::vector<TextKey> mList;
void read(NIFStream* nif) override;
};
struct BSBound : public Extra
{
osg::Vec3f center, halfExtents;
osg::Vec3f mCenter, mExtents;
void read(NIFStream* nif) override;
};
@ -149,7 +102,7 @@ namespace Nif
struct BSInvMarker : public Extra
{
osg::Quat mRotation;
float mScale = 1.0f;
float mScale;
void read(NIFStream* nif) override;
};
@ -162,5 +115,5 @@ namespace Nif
void read(NIFStream* nif) override;
};
} // Namespace
}
#endif

View File

@ -10,15 +10,16 @@
#include <sstream>
#include <stdexcept>
#include "controlled.hpp"
#include "controller.hpp"
#include "data.hpp"
#include "effect.hpp"
#include "exception.hpp"
#include "extra.hpp"
#include "node.hpp"
#include "particle.hpp"
#include "physics.hpp"
#include "property.hpp"
#include "texture.hpp"
namespace Nif
{

View File

@ -0,0 +1,95 @@
#include "particle.hpp"
#include "data.hpp"
namespace Nif
{
void NiParticleModifier::read(NIFStream* nif)
{
mNext.read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
mController.read(nif);
}
void NiParticleModifier::post(Reader& nif)
{
mNext.post(nif);
mController.post(nif);
}
void NiParticleGrowFade::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
nif->read(mGrowTime);
nif->read(mFadeTime);
}
void NiParticleColorModifier::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
mData.read(nif);
}
void NiParticleColorModifier::post(Reader& nif)
{
NiParticleModifier::post(nif);
mData.post(nif);
}
void NiGravity::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
nif->read(mDecay);
nif->read(mForce);
mType = static_cast<ForceType>(nif->get<uint32_t>());
nif->read(mPosition);
nif->read(mDirection);
}
void NiParticleCollider::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
nif->read(mBounceFactor);
if (nif->getVersion() >= NIFStream::generateVersion(4, 2, 0, 2))
{
nif->read(mSpawnOnCollision);
nif->read(mDieOnCollision);
}
}
void NiPlanarCollider::read(NIFStream* nif)
{
NiParticleCollider::read(nif);
nif->read(mExtents);
nif->read(mPosition);
nif->read(mXVector);
nif->read(mYVector);
nif->read(mPlaneNormal);
nif->read(mPlaneDistance);
}
void NiSphericalCollider::read(NIFStream* nif)
{
NiParticleCollider::read(nif);
nif->read(mRadius);
nif->read(mCenter);
}
void NiParticleRotation::read(NIFStream* nif)
{
NiParticleModifier::read(nif);
nif->read(mRandomInitialAxis);
nif->read(mInitialAxis);
nif->read(mRotationSpeed);
}
}

View File

@ -0,0 +1,90 @@
#ifndef OPENMW_COMPONENTS_NIF_PARTICLE_HPP
#define OPENMW_COMPONENTS_NIF_PARTICLE_HPP
#include "base.hpp"
namespace Nif
{
struct NiParticleModifier : public Record
{
NiParticleModifierPtr mNext;
ControllerPtr mController;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct NiParticleGrowFade : public NiParticleModifier
{
float mGrowTime;
float mFadeTime;
void read(NIFStream* nif) override;
};
struct NiParticleColorModifier : public NiParticleModifier
{
NiColorDataPtr mData;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct NiGravity : public NiParticleModifier
{
enum class ForceType : uint32_t
{
Wind = 0, // Fixed direction
Point = 1, // Fixed origin
};
float mDecay{ 0.f };
float mForce;
ForceType mType;
osg::Vec3f mPosition;
osg::Vec3f mDirection;
void read(NIFStream* nif) override;
};
struct NiParticleCollider : public NiParticleModifier
{
float mBounceFactor;
bool mSpawnOnCollision{ false };
bool mDieOnCollision{ false };
void read(NIFStream* nif) override;
};
// NiPinaColada
struct NiPlanarCollider : public NiParticleCollider
{
osg::Vec2f mExtents;
osg::Vec3f mPosition;
osg::Vec3f mXVector, mYVector;
osg::Vec3f mPlaneNormal;
float mPlaneDistance;
void read(NIFStream* nif) override;
};
struct NiSphericalCollider : public NiParticleCollider
{
float mRadius;
osg::Vec3f mCenter;
void read(NIFStream* nif) override;
};
struct NiParticleRotation : public NiParticleModifier
{
uint8_t mRandomInitialAxis;
osg::Vec3f mInitialAxis;
float mRotationSpeed;
void read(NIFStream* nif) override;
};
}
#endif

View File

@ -12,15 +12,15 @@ namespace Nif
void bhkWorldObjCInfoProperty::read(NIFStream* nif)
{
mData = nif->getUInt();
mSize = nif->getUInt();
mCapacityAndFlags = nif->getUInt();
nif->read(mData);
nif->read(mSize);
nif->read(mCapacityAndFlags);
}
void bhkWorldObjectCInfo::read(NIFStream* nif)
{
nif->skip(4); // Unused
mPhaseType = static_cast<BroadPhaseType>(nif->getChar());
mPhaseType = static_cast<BroadPhaseType>(nif->get<uint8_t>());
nif->skip(3); // Unused
mProperty.read(nif);
}
@ -29,47 +29,47 @@ namespace Nif
{
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
nif->skip(4); // Unknown
mMaterial = nif->getUInt();
nif->read(mMaterial);
}
void HavokFilter::read(NIFStream* nif)
{
mLayer = nif->getChar();
mFlags = nif->getChar();
mGroup = nif->getUShort();
nif->read(mLayer);
nif->read(mFlags);
nif->read(mGroup);
}
void hkSubPartData::read(NIFStream* nif)
{
mHavokFilter.read(nif);
mNumVertices = nif->getUInt();
nif->read(mNumVertices);
mHavokMaterial.read(nif);
}
void hkpMoppCode::read(NIFStream* nif)
{
unsigned int size = nif->getUInt();
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
mOffset = nif->getVector4();
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3)
nif->getChar(); // MOPP data build type
nif->readVector(mData, size);
}
void bhkEntityCInfo::read(NIFStream* nif)
{
mResponseType = static_cast<hkResponseType>(nif->getChar());
mResponseType = static_cast<hkResponseType>(nif->get<uint8_t>());
nif->skip(1); // Unused
mProcessContactDelay = nif->getUShort();
nif->read(mProcessContactDelay);
}
void hkpMoppCode::read(NIFStream* nif)
{
uint32_t dataSize;
nif->read(dataSize);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
nif->read(mOffset);
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3)
nif->read(mBuildType);
nif->readVector(mData, dataSize);
}
void TriangleData::read(NIFStream* nif)
{
for (int i = 0; i < 3; i++)
mTriangle[i] = nif->getUShort();
mWeldingInfo = nif->getUShort();
nif->readArray(mTriangle);
nif->read(mWeldingInfo);
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
mNormal = nif->getVector3();
nif->read(mNormal);
}
void bhkMeshMaterial::read(NIFStream* nif)
@ -80,28 +80,27 @@ namespace Nif
void bhkQsTransform::read(NIFStream* nif)
{
mTranslation = nif->getVector4();
mRotation = nif->getQuaternion();
nif->read(mTranslation);
nif->read(mRotation);
}
void bhkCMSBigTri::read(NIFStream* nif)
{
for (int i = 0; i < 3; i++)
mTriangle[i] = nif->getUShort();
mMaterial = nif->getUInt();
mWeldingInfo = nif->getUShort();
nif->readArray(mTriangle);
nif->read(mMaterial);
nif->read(mWeldingInfo);
}
void bhkCMSChunk::read(NIFStream* nif)
{
mTranslation = nif->getVector4();
mMaterialIndex = nif->getUInt();
mReference = nif->getUShort();
mTransformIndex = nif->getUShort();
nif->readVector(mVertices, nif->getUInt());
nif->readVector(mIndices, nif->getUInt());
nif->readVector(mStrips, nif->getUInt());
nif->readVector(mWeldingInfos, nif->getUInt());
nif->read(mTranslation);
nif->read(mMaterialIndex);
nif->read(mReference);
nif->read(mTransformIndex);
nif->readVector(mVertices, nif->get<uint32_t>());
nif->readVector(mIndices, nif->get<uint32_t>());
nif->readVector(mStrips, nif->get<uint32_t>());
nif->readVector(mWeldingInfos, nif->get<uint32_t>());
}
void bhkRigidBodyCInfo::read(NIFStream* nif)
@ -115,64 +114,67 @@ namespace Nif
{
if (nif->getBethVersion() >= 83)
nif->skip(4); // Unused
mResponseType = static_cast<hkResponseType>(nif->getChar());
mResponseType = static_cast<hkResponseType>(nif->get<uint8_t>());
nif->skip(1); // Unused
mProcessContactDelay = nif->getUShort();
nif->read(mProcessContactDelay);
}
}
if (nif->getBethVersion() < 83)
nif->skip(4); // Unused
mTranslation = nif->getVector4();
mRotation = nif->getQuaternion();
mLinearVelocity = nif->getVector4();
mAngularVelocity = nif->getVector4();
nif->read(mTranslation);
nif->read(mRotation);
nif->read(mLinearVelocity);
nif->read(mAngularVelocity);
// A bit hacky, but this is the only instance where a 3x3 matrix has padding.
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
mInertiaTensor[i][j] = nif->getFloat();
mCenter = nif->getVector4();
mMass = nif->getFloat();
mLinearDamping = nif->getFloat();
mAngularDamping = nif->getFloat();
{
nif->read(mInertiaTensor.mValues[i], 3);
nif->skip(4); // Padding
}
nif->read(mCenter);
nif->read(mMass);
nif->read(mLinearDamping);
nif->read(mAngularDamping);
if (nif->getBethVersion() >= 83)
{
if (nif->getBethVersion() != NIFFile::BethVersion::BETHVER_FO4)
mTimeFactor = nif->getFloat();
mGravityFactor = nif->getFloat();
nif->read(mTimeFactor);
nif->read(mGravityFactor);
}
mFriction = nif->getFloat();
nif->read(mFriction);
if (nif->getBethVersion() >= 83)
mRollingFrictionMult = nif->getFloat();
mRestitution = nif->getFloat();
nif->read(mRollingFrictionMult);
nif->read(mRestitution);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
{
mMaxLinearVelocity = nif->getFloat();
mMaxAngularVelocity = nif->getFloat();
nif->read(mMaxLinearVelocity);
nif->read(mMaxAngularVelocity);
if (nif->getBethVersion() != NIFFile::BethVersion::BETHVER_FO4)
mPenetrationDepth = nif->getFloat();
nif->read(mPenetrationDepth);
}
mMotionType = static_cast<hkMotionType>(nif->getChar());
mMotionType = static_cast<hkMotionType>(nif->get<uint8_t>());
if (nif->getBethVersion() < 83)
mDeactivatorType = static_cast<hkDeactivatorType>(nif->getChar());
mDeactivatorType = static_cast<hkDeactivatorType>(nif->get<uint8_t>());
else
mEnableDeactivation = nif->getBoolean();
mSolverDeactivation = static_cast<hkSolverDeactivation>(nif->getChar());
nif->read(mEnableDeactivation);
mSolverDeactivation = static_cast<hkSolverDeactivation>(nif->get<uint8_t>());
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_FO4)
{
nif->skip(1);
mPenetrationDepth = nif->getFloat();
mTimeFactor = nif->getFloat();
nif->read(mPenetrationDepth);
nif->read(mTimeFactor);
nif->skip(4);
mResponseType = static_cast<hkResponseType>(nif->getChar());
mResponseType = static_cast<hkResponseType>(nif->get<uint8_t>());
nif->skip(1); // Unused
mProcessContactDelay = nif->getUShort();
nif->read(mProcessContactDelay);
}
mQualityType = static_cast<hkQualityType>(nif->getChar());
mQualityType = static_cast<hkQualityType>(nif->get<uint8_t>());
if (nif->getBethVersion() >= 83)
{
mAutoRemoveLevel = nif->getChar();
mResponseModifierFlags = nif->getChar();
mNumContactPointShapeKeys = nif->getChar();
mForceCollidedOntoPPU = nif->getBoolean();
nif->read(mAutoRemoveLevel);
nif->read(mResponseModifierFlags);
nif->read(mNumContactPointShapeKeys);
nif->read(mForceCollidedOntoPPU);
}
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_FO4)
nif->skip(3); // Unused
@ -182,7 +184,7 @@ namespace Nif
void bhkConstraintCInfo::read(NIFStream* nif)
{
nif->get<unsigned int>(); // Number of entities, unused
nif->get<uint32_t>(); // Number of entities, unused
mEntityA.read(nif);
mEntityB.read(nif);
@ -203,7 +205,7 @@ namespace Nif
nif->read(mDamping);
nif->read(mProportionalRecoveryVelocity);
nif->read(mConstantRecoveryVelocity);
mEnabled = nif->getBoolean();
nif->read(mEnabled);
}
void bhkVelocityConstraintMotor::read(NIFStream* nif)
@ -212,8 +214,8 @@ namespace Nif
nif->read(mMaxForce);
nif->read(mTau);
nif->read(mTargetVelocity);
mUseVelocityTarget = nif->getBoolean();
mEnabled = nif->getBoolean();
nif->read(mUseVelocityTarget);
nif->read(mEnabled);
}
void bhkSpringDamperConstraintMotor::read(NIFStream* nif)
@ -222,7 +224,7 @@ namespace Nif
nif->read(mMaxForce);
nif->read(mSpringConstant);
nif->read(mSpringDamping);
mEnabled = nif->getBoolean();
nif->read(mEnabled);
}
void bhkConstraintMotorCInfo::read(NIFStream* nif)
@ -335,7 +337,8 @@ namespace Nif
void bhkCollisionObject::read(NIFStream* nif)
{
NiCollisionObject::read(nif);
mFlags = nif->getUShort();
nif->read(mFlags);
mBody.read(nif);
}
@ -356,6 +359,7 @@ namespace Nif
void bhkEntity::read(NIFStream* nif)
{
bhkWorldObject::read(nif);
mInfo.read(nif);
}
@ -372,21 +376,26 @@ namespace Nif
void bhkMoppBvTreeShape::read(NIFStream* nif)
{
bhkBvTreeShape::read(nif);
nif->skip(12); // Unused
mScale = nif->getFloat();
nif->read(mScale);
mMopp.read(nif);
}
void bhkNiTriStripsShape::read(NIFStream* nif)
{
mHavokMaterial.read(nif);
mRadius = nif->getFloat();
nif->read(mRadius);
nif->skip(20); // Unused
mGrowBy = nif->getUInt();
nif->read(mGrowBy);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
mScale = nif->getVector4();
nif->read(mScale);
readRecordList(nif, mData);
nif->readVector(mFilters, nif->getUInt());
uint32_t numFilters;
nif->read(numFilters);
mHavokFilters.resize(numFilters);
for (HavokFilter& filter : mHavokFilters)
filter.read(nif);
}
void bhkNiTriStripsShape::post(Reader& nif)
@ -398,15 +407,17 @@ namespace Nif
{
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
{
mSubshapes.resize(nif->getUShort());
uint16_t numSubshapes;
nif->read(numSubshapes);
mSubshapes.resize(numSubshapes);
for (hkSubPartData& subshape : mSubshapes)
subshape.read(nif);
}
mUserData = nif->getUInt();
nif->read(mUserData);
nif->skip(4); // Unused
mRadius = nif->getFloat();
nif->read(mRadius);
nif->skip(4); // Unused
mScale = nif->getVector4();
nif->read(mScale);
nif->skip(20); // Duplicates of the two previous fields
mData.read(nif);
}
@ -418,22 +429,26 @@ namespace Nif
void hkPackedNiTriStripsData::read(NIFStream* nif)
{
unsigned int numTriangles = nif->getUInt();
uint32_t numTriangles;
nif->read(numTriangles);
mTriangles.resize(numTriangles);
for (unsigned int i = 0; i < numTriangles; i++)
for (uint32_t i = 0; i < numTriangles; i++)
mTriangles[i].read(nif);
unsigned int numVertices = nif->getUInt();
uint32_t numVertices;
nif->read(numVertices);
bool compressed = false;
if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS)
compressed = nif->getBoolean();
nif->read(compressed);
if (!compressed)
nif->readVector(mVertices, numVertices);
else
nif->skip(6 * numVertices); // Half-precision vectors are not currently supported
if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS)
{
mSubshapes.resize(nif->getUShort());
uint16_t numSubshapes;
nif->read(numSubshapes);
mSubshapes.resize(numSubshapes);
for (hkSubPartData& subshape : mSubshapes)
subshape.read(nif);
}
@ -447,23 +462,25 @@ namespace Nif
void bhkConvexShape::read(NIFStream* nif)
{
bhkSphereRepShape::read(nif);
mRadius = nif->getFloat();
nif->read(mRadius);
}
void bhkConvexVerticesShape::read(NIFStream* nif)
{
bhkConvexShape::read(nif);
mVerticesProperty.read(nif);
mNormalsProperty.read(nif);
nif->readVector(mVertices, nif->getUInt());
nif->readVector(mNormals, nif->getUInt());
nif->readVector(mVertices, nif->get<uint32_t>());
nif->readVector(mNormals, nif->get<uint32_t>());
}
void bhkConvexTransformShape::read(NIFStream* nif)
{
mShape.read(nif);
mHavokMaterial.read(nif);
mRadius = nif->getFloat();
nif->read(mRadius);
nif->skip(8); // Unused
std::array<float, 16> mat;
nif->readArray(mat);
@ -478,19 +495,21 @@ namespace Nif
void bhkBoxShape::read(NIFStream* nif)
{
bhkConvexShape::read(nif);
nif->skip(8); // Unused
mExtents = nif->getVector3();
nif->read(mExtents);
nif->skip(4); // Unused
}
void bhkCapsuleShape::read(NIFStream* nif)
{
bhkConvexShape::read(nif);
nif->skip(8); // Unused
mPoint1 = nif->getVector3();
mRadius1 = nif->getFloat();
mPoint2 = nif->getVector3();
mRadius2 = nif->getFloat();
nif->read(mPoint1);
nif->read(mRadius1);
nif->read(mPoint2);
nif->read(mRadius2);
}
void bhkListShape::read(NIFStream* nif)
@ -499,7 +518,8 @@ namespace Nif
mHavokMaterial.read(nif);
mChildShapeProperty.read(nif);
mChildFilterProperty.read(nif);
unsigned int numFilters = nif->getUInt();
uint32_t numFilters;
nif->read(numFilters);
mHavokFilters.resize(numFilters);
for (HavokFilter& filter : mHavokFilters)
filter.read(nif);
@ -508,12 +528,12 @@ namespace Nif
void bhkCompressedMeshShape::read(NIFStream* nif)
{
mTarget.read(nif);
mUserData = nif->getUInt();
mRadius = nif->getFloat();
nif->getFloat(); // Unknown
mScale = nif->getVector4();
nif->getFloat(); // Radius
nif->getVector4(); // Scale
nif->read(mUserData);
nif->read(mRadius);
nif->skip(4); // Unknown
nif->read(mScale);
nif->skip(4); // Radius
nif->skip(16); // Scale
mData.read(nif);
}
@ -525,60 +545,66 @@ namespace Nif
void bhkCompressedMeshShapeData::read(NIFStream* nif)
{
mBitsPerIndex = nif->getUInt();
mBitsPerWIndex = nif->getUInt();
mMaskWIndex = nif->getUInt();
mMaskIndex = nif->getUInt();
mError = nif->getFloat();
mAabbMin = nif->getVector4();
mAabbMax = nif->getVector4();
mWeldingType = nif->getChar();
mMaterialType = nif->getChar();
nif->skip(nif->getUInt() * 4); // Unused
nif->skip(nif->getUInt() * 4); // Unused
nif->skip(nif->getUInt() * 4); // Unused
nif->read(mBitsPerIndex);
nif->read(mBitsPerWIndex);
nif->read(mMaskWIndex);
nif->read(mMaskIndex);
nif->read(mError);
nif->read(mAabbMin);
nif->read(mAabbMax);
nif->read(mWeldingType);
nif->read(mMaterialType);
nif->skip(nif->get<uint32_t>() * 4); // Unused
nif->skip(nif->get<uint32_t>() * 4); // Unused
nif->skip(nif->get<uint32_t>() * 4); // Unused
size_t numMaterials = nif->getUInt();
uint32_t numMaterials;
nif->read(numMaterials);
mMaterials.resize(numMaterials);
for (bhkMeshMaterial& material : mMaterials)
material.read(nif);
nif->getUInt(); // Unused
size_t numTransforms = nif->getUInt();
nif->skip(4); // Unused
uint32_t numTransforms;
nif->read(numTransforms);
mChunkTransforms.resize(numTransforms);
for (bhkQsTransform& transform : mChunkTransforms)
transform.read(nif);
nif->readVector(mBigVerts, nif->getUInt());
nif->readVector(mBigVerts, nif->get<uint32_t>());
size_t numBigTriangles = nif->getUInt();
uint32_t numBigTriangles;
nif->read(numBigTriangles);
mBigTris.resize(numBigTriangles);
for (bhkCMSBigTri& tri : mBigTris)
tri.read(nif);
size_t numChunks = nif->getUInt();
uint32_t numChunks;
nif->read(numChunks);
mChunks.resize(numChunks);
for (bhkCMSChunk& chunk : mChunks)
chunk.read(nif);
nif->getUInt(); // Unused
nif->skip(4); // Unused
}
void bhkRigidBody::read(NIFStream* nif)
{
bhkEntity::read(nif);
mInfo.read(nif);
readRecordList(nif, mConstraints);
if (nif->getBethVersion() < 76)
mBodyFlags = nif->getUInt();
nif->read(mBodyFlags);
else
mBodyFlags = nif->getUShort();
mBodyFlags = nif->get<uint16_t>();
}
void bhkSimpleShapePhantom::read(NIFStream* nif)
{
bhkWorldObject::read(nif);
nif->skip(8); // Unused
std::array<float, 16> mat;
nif->readArray(mat);
@ -598,18 +624,21 @@ namespace Nif
void bhkRagdollConstraint::read(NIFStream* nif)
{
bhkConstraint::read(nif);
mConstraint.read(nif);
}
void bhkHingeConstraint::read(NIFStream* nif)
{
bhkConstraint::read(nif);
mConstraint.read(nif);
}
void bhkLimitedHingeConstraint::read(NIFStream* nif)
{
bhkConstraint::read(nif);
mConstraint.read(nif);
}

View File

@ -1,6 +1,7 @@
#ifndef OPENMW_COMPONENTS_NIF_PHYSICS_HPP
#define OPENMW_COMPONENTS_NIF_PHYSICS_HPP
#include "niftypes.hpp"
#include "record.hpp"
#include "recordptr.hpp"
@ -23,9 +24,10 @@ namespace Nif
struct bhkWorldObjCInfoProperty
{
unsigned int mData;
unsigned int mSize;
unsigned int mCapacityAndFlags;
uint32_t mData;
uint32_t mSize;
uint32_t mCapacityAndFlags;
void read(NIFStream* nif);
};
@ -41,28 +43,32 @@ namespace Nif
{
BroadPhaseType mPhaseType;
bhkWorldObjCInfoProperty mProperty;
void read(NIFStream* nif);
};
struct HavokMaterial
{
unsigned int mMaterial;
uint32_t mMaterial;
void read(NIFStream* nif);
};
struct HavokFilter
{
unsigned char mLayer;
unsigned char mFlags;
unsigned short mGroup;
uint8_t mLayer;
uint8_t mFlags;
uint16_t mGroup;
void read(NIFStream* nif);
};
struct hkSubPartData
{
HavokMaterial mHavokMaterial;
unsigned int mNumVertices;
uint32_t mNumVertices;
HavokFilter mHavokFilter;
void read(NIFStream* nif);
};
@ -77,22 +83,26 @@ namespace Nif
struct bhkEntityCInfo
{
hkResponseType mResponseType;
unsigned short mProcessContactDelay;
uint16_t mProcessContactDelay;
void read(NIFStream* nif);
};
struct hkpMoppCode
{
osg::Vec4f mOffset;
std::vector<char> mData;
uint8_t mBuildType;
std::vector<uint8_t> mData;
void read(NIFStream* nif);
};
struct TriangleData
{
unsigned short mTriangle[3];
unsigned short mWeldingInfo;
std::array<uint16_t, 3> mTriangle;
uint16_t mWeldingInfo;
osg::Vec3f mNormal;
void read(NIFStream* nif);
};
@ -100,6 +110,7 @@ namespace Nif
{
HavokMaterial mHavokMaterial;
HavokFilter mHavokFilter;
void read(NIFStream* nif);
};
@ -107,27 +118,30 @@ namespace Nif
{
osg::Vec4f mTranslation;
osg::Quat mRotation;
void read(NIFStream* nif);
};
struct bhkCMSBigTri
{
unsigned short mTriangle[3];
unsigned int mMaterial;
unsigned short mWeldingInfo;
std::array<uint16_t, 3> mTriangle;
uint32_t mMaterial;
uint16_t mWeldingInfo;
void read(NIFStream* nif);
};
struct bhkCMSChunk
{
osg::Vec4f mTranslation;
unsigned int mMaterialIndex;
unsigned short mReference;
unsigned short mTransformIndex;
std::vector<unsigned short> mVertices;
std::vector<unsigned short> mIndices;
std::vector<unsigned short> mStrips;
std::vector<unsigned short> mWeldingInfos;
uint32_t mMaterialIndex;
uint16_t mReference;
uint16_t mTransformIndex;
std::vector<uint16_t> mVertices;
std::vector<uint16_t> mIndices;
std::vector<uint16_t> mStrips;
std::vector<uint16_t> mWeldingInfos;
void read(NIFStream* nif);
};
@ -180,12 +194,12 @@ namespace Nif
{
HavokFilter mHavokFilter;
hkResponseType mResponseType;
unsigned short mProcessContactDelay;
uint16_t mProcessContactDelay;
osg::Vec4f mTranslation;
osg::Quat mRotation;
osg::Vec4f mLinearVelocity;
osg::Vec4f mAngularVelocity;
float mInertiaTensor[3][4];
Matrix3 mInertiaTensor;
osg::Vec4f mCenter;
float mMass;
float mLinearDamping;
@ -203,10 +217,11 @@ namespace Nif
bool mEnableDeactivation{ true };
hkSolverDeactivation mSolverDeactivation;
hkQualityType mQualityType;
unsigned char mAutoRemoveLevel;
unsigned char mResponseModifierFlags;
unsigned char mNumContactPointShapeKeys;
uint8_t mAutoRemoveLevel;
uint8_t mResponseModifierFlags;
uint8_t mNumContactPointShapeKeys;
bool mForceCollidedOntoPPU;
void read(NIFStream* nif);
};
@ -222,6 +237,7 @@ namespace Nif
bhkEntityPtr mEntityA;
bhkEntityPtr mEntityB;
ConstraintPriority mPriority;
void read(NIFStream* nif);
void post(Reader& nif);
};
@ -242,6 +258,7 @@ namespace Nif
float mProportionalRecoveryVelocity;
float mConstantRecoveryVelocity;
bool mEnabled;
void read(NIFStream* nif);
};
@ -252,6 +269,7 @@ namespace Nif
float mTargetVelocity;
bool mUseVelocityTarget;
bool mEnabled;
void read(NIFStream* nif);
};
@ -261,6 +279,7 @@ namespace Nif
float mSpringConstant;
float mSpringDamping;
bool mEnabled;
void read(NIFStream* nif);
};
@ -270,6 +289,7 @@ namespace Nif
bhkPositionConstraintMotor mPositionMotor;
bhkVelocityConstraintMotor mVelocityMotor;
bhkSpringDamperConstraintMotor mSpringDamperMotor;
void read(NIFStream* nif);
};
@ -289,6 +309,7 @@ namespace Nif
float mTwistMinAngle, mTwistMaxAngle;
float mMaxFriction;
bhkConstraintMotorCInfo mMotor;
void read(NIFStream* nif);
};
@ -301,8 +322,10 @@ namespace Nif
osg::Vec4f mPerpAxis1;
osg::Vec4f mPerpAxis2;
};
HingeData mDataA;
HingeData mDataB;
void read(NIFStream* nif);
};
@ -315,11 +338,13 @@ namespace Nif
osg::Vec4f mPerpAxis1;
osg::Vec4f mPerpAxis2;
};
HingeData mDataA;
HingeData mDataB;
float mMinAngle, mMaxAngle;
float mMaxFriction;
bhkConstraintMotorCInfo mMotor;
void read(NIFStream* nif);
};
@ -358,7 +383,7 @@ namespace Nif
// Bethesda Havok-specific collision object
struct bhkCollisionObject : public NiCollisionObject
{
unsigned short mFlags;
uint16_t mFlags;
bhkWorldObjectPtr mBody;
void read(NIFStream* nif) override;
@ -375,6 +400,7 @@ namespace Nif
bhkShapePtr mShape;
HavokFilter mHavokFilter;
bhkWorldObjectCInfo mWorldObjectInfo;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
@ -383,6 +409,7 @@ namespace Nif
struct bhkEntity : public bhkWorldObject
{
bhkEntityCInfo mInfo;
void read(NIFStream* nif) override;
};
@ -391,6 +418,7 @@ namespace Nif
struct bhkBvTreeShape : public bhkShape
{
bhkShapePtr mShape;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
@ -400,6 +428,7 @@ namespace Nif
{
float mScale;
hkpMoppCode mMopp;
void read(NIFStream* nif) override;
};
@ -408,10 +437,11 @@ namespace Nif
{
HavokMaterial mHavokMaterial;
float mRadius;
unsigned int mGrowBy;
uint32_t mGrowBy;
osg::Vec4f mScale{ 1.f, 1.f, 1.f, 0.f };
NiTriStripsDataList mData;
std::vector<unsigned int> mFilters;
std::vector<HavokFilter> mHavokFilters;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
@ -420,7 +450,7 @@ namespace Nif
struct bhkPackedNiTriStripsShape : public bhkShapeCollection
{
std::vector<hkSubPartData> mSubshapes;
unsigned int mUserData;
uint32_t mUserData;
float mRadius;
osg::Vec4f mScale;
hkPackedNiTriStripsDataPtr mData;
@ -435,6 +465,7 @@ namespace Nif
std::vector<TriangleData> mTriangles;
std::vector<osg::Vec3f> mVertices;
std::vector<hkSubPartData> mSubshapes;
void read(NIFStream* nif) override;
};
@ -442,6 +473,7 @@ namespace Nif
struct bhkSphereRepShape : public bhkShape
{
HavokMaterial mHavokMaterial;
void read(NIFStream* nif) override;
};
@ -449,6 +481,7 @@ namespace Nif
struct bhkConvexShape : public bhkSphereRepShape
{
float mRadius;
void read(NIFStream* nif) override;
};
@ -459,6 +492,7 @@ namespace Nif
bhkWorldObjCInfoProperty mNormalsProperty;
std::vector<osg::Vec4f> mVertices;
std::vector<osg::Vec4f> mNormals;
void read(NIFStream* nif) override;
};
@ -468,6 +502,7 @@ namespace Nif
HavokMaterial mHavokMaterial;
float mRadius;
osg::Matrixf mTransform;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
@ -476,6 +511,7 @@ namespace Nif
struct bhkBoxShape : public bhkConvexShape
{
osg::Vec3f mExtents;
void read(NIFStream* nif) override;
};
@ -499,28 +535,30 @@ namespace Nif
bhkWorldObjCInfoProperty mChildShapeProperty;
bhkWorldObjCInfoProperty mChildFilterProperty;
std::vector<HavokFilter> mHavokFilters;
void read(NIFStream* nif) override;
};
struct bhkCompressedMeshShape : public bhkShape
{
NodePtr mTarget;
unsigned int mUserData;
uint32_t mUserData;
float mRadius;
osg::Vec4f mScale;
bhkCompressedMeshShapeDataPtr mData;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct bhkCompressedMeshShapeData : public bhkRefObject
{
unsigned int mBitsPerIndex, mBitsPerWIndex;
unsigned int mMaskWIndex, mMaskIndex;
uint32_t mBitsPerIndex, mBitsPerWIndex;
uint32_t mMaskWIndex, mMaskIndex;
float mError;
osg::Vec4f mAabbMin, mAabbMax;
char mWeldingType;
char mMaterialType;
uint8_t mWeldingType;
uint8_t mMaterialType;
std::vector<bhkMeshMaterial> mMaterials;
std::vector<bhkQsTransform> mChunkTransforms;
std::vector<osg::Vec4f> mBigVerts;
@ -534,7 +572,7 @@ namespace Nif
{
bhkRigidBodyCInfo mInfo;
bhkSerializableList mConstraints;
unsigned int mBodyFlags;
uint32_t mBodyFlags;
void read(NIFStream* nif) override;
};
@ -542,6 +580,7 @@ namespace Nif
struct bhkSimpleShapePhantom : public bhkWorldObject
{
osg::Matrixf mTransform;
void read(NIFStream* nif) override;
};
@ -549,6 +588,7 @@ namespace Nif
struct bhkConstraint : public bhkSerializable
{
bhkConstraintCInfo mInfo;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
@ -556,18 +596,21 @@ namespace Nif
struct bhkRagdollConstraint : public bhkConstraint
{
bhkRagdollConstraintCInfo mConstraint;
void read(NIFStream* nif) override;
};
struct bhkHingeConstraint : public bhkConstraint
{
bhkHingeConstraintCInfo mConstraint;
void read(NIFStream* nif) override;
};
struct bhkLimitedHingeConstraint : public bhkConstraint
{
bhkLimitedHingeConstraintCInfo mConstraint;
void read(NIFStream* nif) override;
};

View File

@ -1,7 +1,7 @@
#include "property.hpp"
#include "controlled.hpp"
#include "data.hpp"
#include "texture.hpp"
namespace Nif
{

View File

@ -0,0 +1,47 @@
#include "texture.hpp"
#include "data.hpp"
namespace Nif
{
void NiSourceTexture::read(NIFStream* nif)
{
NiTexture::read(nif);
nif->read(mExternal);
if (mExternal || nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
nif->read(mFile);
bool hasData = nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 4);
if (!hasData && !mExternal)
nif->read(hasData);
if (hasData)
mData.read(nif);
mPrefs.mPixelLayout = static_cast<PixelLayout>(nif->get<uint32_t>());
mPrefs.mUseMipMaps = static_cast<MipMapFormat>(nif->get<uint32_t>());
mPrefs.mAlphaFormat = static_cast<AlphaFormat>(nif->get<uint32_t>());
nif->read(mIsStatic);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 103))
{
nif->read(mDirectRendering);
if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 4))
nif->read(mPersistRenderData);
}
}
void NiSourceTexture::post(Reader& nif)
{
NiTexture::post(nif);
mData.post(nif);
}
void BSShaderTextureSet::read(NIFStream* nif)
{
nif->getSizedStrings(mTextures, nif->get<uint32_t>());
}
}

View File

@ -0,0 +1,81 @@
#ifndef OPENMW_COMPONENTS_NIF_TEXTURE_HPP
#define OPENMW_COMPONENTS_NIF_TEXTURE_HPP
#include "base.hpp"
namespace Nif
{
struct NiTexture : public Named
{
};
struct NiSourceTexture : public NiTexture
{
enum class PixelLayout : uint32_t
{
Palette = 0,
HighColor = 1,
TrueColor = 2,
Compressed = 3,
BumpMap = 4,
Default = 5,
};
enum class MipMapFormat : uint32_t
{
No = 0,
Yes = 1,
Default = 2,
};
enum class AlphaFormat : uint32_t
{
None = 0,
Binary = 1,
Smooth = 2,
Default = 3,
};
struct FormatPrefs
{
PixelLayout mPixelLayout;
MipMapFormat mUseMipMaps;
AlphaFormat mAlphaFormat;
};
char mExternal; // References external file
std::string mFile;
NiPixelDataPtr mData;
FormatPrefs mPrefs;
char mIsStatic{ 1 };
bool mDirectRendering{ true };
bool mPersistRenderData{ false };
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct BSShaderTextureSet : public Record
{
enum class TextureType : uint32_t
{
Base = 0,
Normal = 1,
Glow = 2,
Parallax = 3,
Environment = 4,
EnvironmentMask = 5,
Subsurface = 6,
BackLighting = 7,
};
std::vector<std::string> mTextures;
void read(NIFStream* nif) override;
};
}
#endif

View File

@ -305,7 +305,7 @@ namespace NifBullet
// Check for extra data
std::vector<Nif::ExtraPtr> extraCollection;
for (Nif::ExtraPtr e = node.extra; !e.empty(); e = e->next)
for (Nif::ExtraPtr e = node.extra; !e.empty(); e = e->mNext)
extraCollection.emplace_back(e);
for (const auto& extraNode : node.extralist)
if (!extraNode.empty())
@ -316,29 +316,30 @@ namespace NifBullet
{
// String markers may contain important information
// affecting the entire subtree of this node
Nif::NiStringExtraData* sd = (Nif::NiStringExtraData*)e.getPtr();
auto sd = static_cast<const Nif::NiStringExtraData*>(e.getPtr());
if (Misc::StringUtils::ciStartsWith(sd->string, "NC"))
if (Misc::StringUtils::ciStartsWith(sd->mData, "NC"))
{
// NCC flag in vanilla is partly case sensitive: prefix NC is case insensitive but second C needs be
// uppercase
if (sd->string.length() > 2 && sd->string[2] == 'C')
if (sd->mData.length() > 2 && sd->mData[2] == 'C')
// Collide only with camera.
visualCollisionType = Resource::VisualCollisionType::Camera;
else
// No collision.
visualCollisionType = Resource::VisualCollisionType::Default;
}
else if (sd->string == "MRK" && args.mAutogenerated)
// Don't autogenerate collision if MRK is set.
// FIXME: verify if this covers the entire subtree
else if (sd->mData == "MRK" && args.mAutogenerated)
{
// Marker can still have collision if the model explicitely specifies it via a RootCollisionNode.
return;
}
}
else if (e->recType == Nif::RC_BSXFlags)
{
auto bsxFlags = static_cast<const Nif::NiIntegerExtraData*>(e.getPtr());
if (bsxFlags->data & 32) // Editor marker flag
if (bsxFlags->mData & 32) // Editor marker flag
args.mHasMarkers = true;
}
}

View File

@ -42,13 +42,14 @@
#include <osg/TexEnvCombine>
#include <osg/Texture2D>
#include <components/nif/controlled.hpp>
#include <components/nif/effect.hpp>
#include <components/nif/exception.hpp>
#include <components/nif/extra.hpp>
#include <components/nif/niffile.hpp>
#include <components/nif/node.hpp>
#include <components/nif/particle.hpp>
#include <components/nif/property.hpp>
#include <components/nif/texture.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometry.hpp>
@ -174,16 +175,16 @@ namespace
void extractTextKeys(const Nif::NiTextKeyExtraData* tk, SceneUtil::TextKeyMap& textkeys)
{
for (size_t i = 0; i < tk->list.size(); i++)
for (const Nif::NiTextKeyExtraData::TextKey& key : tk->mList)
{
std::vector<std::string> results;
Misc::StringUtils::split(tk->list[i].text, results, "\r\n");
Misc::StringUtils::split(key.mText, results, "\r\n");
for (std::string& result : results)
{
Misc::StringUtils::trim(result);
Misc::StringUtils::lowerCaseInPlace(result);
if (!result.empty())
textkeys.emplace(tk->list[i].time, std::move(result));
textkeys.emplace(key.mTime, std::move(result));
}
}
}
@ -285,9 +286,9 @@ namespace NifOsg
extractTextKeys(static_cast<const Nif::NiTextKeyExtraData*>(extra.getPtr()), target.mTextKeys);
extra = extra->next;
extra = extra->mNext;
Nif::ControllerPtr ctrl = seq->controller;
for (; !extra.empty() && !ctrl.empty(); (extra = extra->next), (ctrl = ctrl->next))
for (; !extra.empty() && !ctrl.empty(); (extra = extra->mNext), (ctrl = ctrl->next))
{
if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController)
{
@ -315,8 +316,8 @@ namespace NifOsg
osg::ref_ptr<SceneUtil::KeyframeController> callback = new NifOsg::KeyframeController(key);
setupController(key, callback, /*animflags*/ 0);
if (!target.mKeyframeControllers.emplace(strdata->string, callback).second)
Log(Debug::Verbose) << "Controller " << strdata->string << " present more than once in "
if (!target.mKeyframeControllers.emplace(strdata->mData, callback).second)
Log(Debug::Verbose) << "Controller " << strdata->mData << " present more than once in "
<< nif.getFilename() << ", ignoring later version";
}
}
@ -509,15 +510,15 @@ namespace NifOsg
return nullptr;
osg::ref_ptr<osg::Image> image;
if (!st->external && !st->data.empty())
if (st->mExternal)
{
image = handleInternalTexture(st->data.getPtr());
}
else
{
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, imageManager->getVFS());
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->mFile, imageManager->getVFS());
image = imageManager->getImage(filename);
}
else if (!st->mData.empty())
{
image = handleInternalTexture(st->mData.getPtr());
}
return image;
}
@ -536,38 +537,41 @@ namespace NifOsg
}
const Nif::NiTextureEffect* textureEffect = static_cast<const Nif::NiTextureEffect*>(nifNode);
if (textureEffect->textureType != Nif::NiTextureEffect::Environment_Map)
if (!textureEffect->mSwitchState)
return false;
if (textureEffect->mTextureType != Nif::NiTextureEffect::TextureType::EnvironmentMap)
{
Log(Debug::Info) << "Unhandled NiTextureEffect type " << textureEffect->textureType << " in "
<< mFilename;
Log(Debug::Info) << "Unhandled NiTextureEffect type "
<< static_cast<uint32_t>(textureEffect->mTextureType) << " in " << mFilename;
return false;
}
if (textureEffect->texture.empty())
if (textureEffect->mTexture.empty())
{
Log(Debug::Info) << "NiTextureEffect missing source texture in " << mFilename;
return false;
}
osg::ref_ptr<osg::TexGen> texGen(new osg::TexGen);
switch (textureEffect->coordGenType)
switch (textureEffect->mCoordGenType)
{
case Nif::NiTextureEffect::World_Parallel:
case Nif::NiTextureEffect::CoordGenType::WorldParallel:
texGen->setMode(osg::TexGen::OBJECT_LINEAR);
break;
case Nif::NiTextureEffect::World_Perspective:
case Nif::NiTextureEffect::CoordGenType::WorldPerspective:
texGen->setMode(osg::TexGen::EYE_LINEAR);
break;
case Nif::NiTextureEffect::Sphere_Map:
case Nif::NiTextureEffect::CoordGenType::SphereMap:
texGen->setMode(osg::TexGen::SPHERE_MAP);
break;
default:
Log(Debug::Info) << "Unhandled NiTextureEffect coordGenType " << textureEffect->coordGenType
<< " in " << mFilename;
Log(Debug::Info) << "Unhandled NiTextureEffect CoordGenType "
<< static_cast<uint32_t>(textureEffect->mCoordGenType) << " in " << mFilename;
return false;
}
osg::ref_ptr<osg::Image> image(handleSourceTexture(textureEffect->texture.getPtr(), imageManager));
osg::ref_ptr<osg::Image> image(handleSourceTexture(textureEffect->mTexture.getPtr(), imageManager));
osg::ref_ptr<osg::Texture2D> texture2d(new osg::Texture2D(image));
if (image)
texture2d->setTextureSize(image->s(), image->t());
@ -644,7 +648,7 @@ namespace NifOsg
std::vector<Nif::ExtraPtr> extraCollection;
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next)
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->mNext)
extraCollection.emplace_back(e);
for (const auto& extraNode : nifNode->extralist)
@ -666,25 +670,25 @@ namespace NifOsg
// String markers may contain important information
// affecting the entire subtree of this obj
if (sd->string == "MRK" && !Loader::getShowMarkers())
if (sd->mData == "MRK" && !Loader::getShowMarkers())
{
// Marker objects. These meshes are only visible in the editor.
args.mHasMarkers = true;
}
else if (sd->string == "BONE")
else if (sd->mData == "BONE")
{
node->getOrCreateUserDataContainer()->addDescription("CustomBone");
}
else if (sd->string.rfind(extraDataIdentifer, 0) == 0)
else if (sd->mData.rfind(extraDataIdentifer, 0) == 0)
{
node->setUserValue(
Misc::OsgUserValues::sExtraData, sd->string.substr(extraDataIdentifer.length()));
Misc::OsgUserValues::sExtraData, sd->mData.substr(extraDataIdentifer.length()));
}
}
else if (e->recType == Nif::RC_BSXFlags)
{
auto bsxFlags = static_cast<const Nif::NiIntegerExtraData*>(e.getPtr());
if (bsxFlags->data & 32) // Editor marker flag
if (bsxFlags->mData & 32) // Editor marker flag
args.mHasMarkers = true;
}
}
@ -895,7 +899,7 @@ namespace NifOsg
if (!key->mInterpolator.empty() && key->mInterpolator->recType != Nif::RC_NiTransformInterpolator)
{
Log(Debug::Error) << "Unsupported interpolator type for NiKeyframeController " << key->recIndex
<< " in " << mFilename;
<< " in " << mFilename << ": " << key->mInterpolator->recName;
continue;
}
osg::ref_ptr<KeyframeController> callback = new KeyframeController(key);
@ -922,7 +926,7 @@ namespace NifOsg
&& visctrl->mInterpolator->recType != Nif::RC_NiBoolInterpolator)
{
Log(Debug::Error) << "Unsupported interpolator type for NiVisController " << visctrl->recIndex
<< " in " << mFilename;
<< " in " << mFilename << ": " << visctrl->mInterpolator->recName;
continue;
}
osg::ref_ptr<VisController> callback(new VisController(visctrl, Loader::getHiddenNodeMask()));
@ -938,7 +942,7 @@ namespace NifOsg
&& rollctrl->mInterpolator->recType != Nif::RC_NiFloatInterpolator)
{
Log(Debug::Error) << "Unsupported interpolator type for NiRollController " << rollctrl->recIndex
<< " in " << mFilename;
<< " in " << mFilename << ": " << rollctrl->mInterpolator->recName;
continue;
}
osg::ref_ptr<RollController> callback = new RollController(rollctrl);
@ -973,8 +977,9 @@ namespace NifOsg
if (!alphactrl->mInterpolator.empty()
&& alphactrl->mInterpolator->recType != Nif::RC_NiFloatInterpolator)
{
Log(Debug::Error) << "Unsupported interpolator type for NiAlphaController "
<< alphactrl->recIndex << " in " << mFilename;
Log(Debug::Error)
<< "Unsupported interpolator type for NiAlphaController " << alphactrl->recIndex << " in "
<< mFilename << ": " << alphactrl->mInterpolator->recName;
continue;
}
osg::ref_ptr<AlphaController> osgctrl = new AlphaController(alphactrl, baseMaterial);
@ -994,8 +999,9 @@ namespace NifOsg
if (!matctrl->mInterpolator.empty()
&& matctrl->mInterpolator->recType != Nif::RC_NiPoint3Interpolator)
{
Log(Debug::Error) << "Unsupported interpolator type for NiMaterialColorController "
<< matctrl->recIndex << " in " << mFilename;
Log(Debug::Error)
<< "Unsupported interpolator type for NiMaterialColorController " << matctrl->recIndex
<< " in " << mFilename << ": " << matctrl->mInterpolator->recName;
continue;
}
osg::ref_ptr<MaterialColorController> osgctrl = new MaterialColorController(matctrl, baseMaterial);
@ -1021,7 +1027,7 @@ namespace NifOsg
&& flipctrl->mInterpolator->recType != Nif::RC_NiFloatInterpolator)
{
Log(Debug::Error) << "Unsupported interpolator type for NiFlipController " << flipctrl->recIndex
<< " in " << mFilename;
<< " in " << mFilename << ": " << flipctrl->mInterpolator->recName;
continue;
}
std::vector<osg::ref_ptr<osg::Texture2D>> textures;
@ -1067,12 +1073,12 @@ namespace NifOsg
attachTo->addChild(program);
program->setParticleSystem(partsys);
program->setReferenceFrame(rf);
for (; !affectors.empty(); affectors = affectors->next)
for (; !affectors.empty(); affectors = affectors->mNext)
{
if (affectors->recType == Nif::RC_NiParticleGrowFade)
{
const Nif::NiParticleGrowFade* gf = static_cast<const Nif::NiParticleGrowFade*>(affectors.getPtr());
program->addOperator(new GrowFadeAffector(gf->growTime, gf->fadeTime));
program->addOperator(new GrowFadeAffector(gf->mGrowTime, gf->mFadeTime));
}
else if (affectors->recType == Nif::RC_NiGravity)
{
@ -1083,9 +1089,9 @@ namespace NifOsg
{
const Nif::NiParticleColorModifier* cl
= static_cast<const Nif::NiParticleColorModifier*>(affectors.getPtr());
if (cl->data.empty())
if (cl->mData.empty())
continue;
const Nif::NiColorData* clrdata = cl->data.getPtr();
const Nif::NiColorData* clrdata = cl->mData.getPtr();
program->addOperator(new ParticleColorAffector(clrdata));
}
else if (affectors->recType == Nif::RC_NiParticleRotation)
@ -1095,7 +1101,7 @@ namespace NifOsg
else
Log(Debug::Info) << "Unhandled particle modifier " << affectors->recName << " in " << mFilename;
}
for (; !colliders.empty(); colliders = colliders->next)
for (; !colliders.empty(); colliders = colliders->mNext)
{
if (colliders->recType == Nif::RC_NiPlanarCollider)
{
@ -2008,15 +2014,15 @@ namespace NifOsg
const unsigned int uvSet = 0;
for (size_t i = 0; i < textureSet->textures.size(); ++i)
for (size_t i = 0; i < textureSet->mTextures.size(); ++i)
{
if (textureSet->textures[i].empty())
if (textureSet->mTextures[i].empty())
continue;
switch (i)
switch (static_cast<Nif::BSShaderTextureSet::TextureType>(i))
{
case Nif::BSShaderTextureSet::TextureType_Base:
case Nif::BSShaderTextureSet::TextureType_Normal:
case Nif::BSShaderTextureSet::TextureType_Glow:
case Nif::BSShaderTextureSet::TextureType::Base:
case Nif::BSShaderTextureSet::TextureType::Normal:
case Nif::BSShaderTextureSet::TextureType::Glow:
break;
default:
{
@ -2026,7 +2032,7 @@ namespace NifOsg
}
}
std::string filename
= Misc::ResourceHelpers::correctTexturePath(textureSet->textures[i], imageManager->getVFS());
= Misc::ResourceHelpers::correctTexturePath(textureSet->mTextures[i], imageManager->getVFS());
osg::ref_ptr<osg::Image> image = imageManager->getImage(filename);
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
if (image)
@ -2035,17 +2041,19 @@ namespace NifOsg
unsigned int texUnit = boundTextures.size();
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
// BSShaderTextureSet presence means there's no need for FFP support for the affected node
switch (i)
switch (static_cast<Nif::BSShaderTextureSet::TextureType>(i))
{
case Nif::BSShaderTextureSet::TextureType_Base:
case Nif::BSShaderTextureSet::TextureType::Base:
texture2d->setName("diffuseMap");
break;
case Nif::BSShaderTextureSet::TextureType_Normal:
case Nif::BSShaderTextureSet::TextureType::Normal:
texture2d->setName("normalMap");
break;
case Nif::BSShaderTextureSet::TextureType_Glow:
case Nif::BSShaderTextureSet::TextureType::Glow:
texture2d->setName("emissiveMap");
break;
default:
break;
}
boundTextures.emplace_back(uvSet);
}

View File

@ -9,7 +9,6 @@
#include <components/debug/debuglog.hpp>
#include <components/misc/rng.hpp>
#include <components/nif/controlled.hpp>
#include <components/nif/data.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometry.hpp>
@ -281,20 +280,13 @@ namespace NifOsg
GravityAffector::GravityAffector(const Nif::NiGravity* gravity)
: mForce(gravity->mForce)
, mType(static_cast<ForceType>(gravity->mType))
, mType(gravity->mType)
, mPosition(gravity->mPosition)
, mDirection(gravity->mDirection)
, mDecay(gravity->mDecay)
{
}
GravityAffector::GravityAffector()
: mForce(0)
, mType(Type_Wind)
, mDecay(0.f)
{
}
GravityAffector::GravityAffector(const GravityAffector& copy, const osg::CopyOp& copyop)
: osgParticle::Operator(copy, copyop)
{
@ -311,8 +303,8 @@ namespace NifOsg
{
bool absolute = (program->getReferenceFrame() == osgParticle::ParticleProcessor::ABSOLUTE_RF);
if (mType == Type_Point
|| mDecay != 0.f) // we don't need the position for Wind gravity, except if decay is being applied
// We don't need the position for Wind gravity, except if decay is being applied
if (mType == Nif::NiGravity::ForceType::Point || mDecay != 0.f)
mCachedWorldPosition = absolute ? program->transformLocalToWorld(mPosition) : mPosition;
mCachedWorldDirection = absolute ? program->rotateLocalToWorld(mDirection) : mDirection;
@ -324,7 +316,7 @@ namespace NifOsg
const float magic = 1.6f;
switch (mType)
{
case Type_Wind:
case Nif::NiGravity::ForceType::Wind:
{
float decayFactor = 1.f;
if (mDecay != 0.f)
@ -338,7 +330,7 @@ namespace NifOsg
break;
}
case Type_Point:
case Nif::NiGravity::ForceType::Point:
{
osg::Vec3f diff = mCachedWorldPosition - particle->getPosition();

View File

@ -10,15 +10,14 @@
#include <osgParticle/Placer>
#include <osgParticle/Shooter>
#include <components/nif/particle.hpp> // NiGravity::ForceType
#include <components/sceneutil/nodecallback.hpp>
#include "controller.hpp" // ValueInterpolator
namespace Nif
{
struct NiGravity;
struct NiPlanarCollider;
struct NiSphericalCollider;
struct NiColorData;
}
@ -180,7 +179,7 @@ namespace NifOsg
{
public:
GravityAffector(const Nif::NiGravity* gravity);
GravityAffector();
GravityAffector() = default;
GravityAffector(const GravityAffector& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
GravityAffector& operator=(const GravityAffector&) = delete;
@ -191,16 +190,11 @@ namespace NifOsg
void beginOperate(osgParticle::Program*) override;
private:
float mForce;
enum ForceType
{
Type_Wind,
Type_Point
};
ForceType mType;
float mForce{ 0.f };
Nif::NiGravity::ForceType mType{ Nif::NiGravity::ForceType::Wind };
osg::Vec3f mPosition;
osg::Vec3f mDirection;
float mDecay;
float mDecay{ 0.f };
osg::Vec3f mCachedWorldPosition;
osg::Vec3f mCachedWorldDirection;
};