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) inline void init(Extra& value)
{ {
value.next = ExtraPtr(nullptr); value.mNext = ExtraPtr(nullptr);
} }
inline void init(Named& value) inline void init(Named& value)

View File

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

View File

@ -111,7 +111,7 @@ add_component_dir (sceneutil
) )
add_component_dir (nif 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 add_component_dir (nifosg

View File

@ -5,11 +5,11 @@ namespace Nif
void Extra::read(NIFStream* nif) void Extra::read(NIFStream* nif)
{ {
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0)) 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)) else if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
{ {
next.read(nif); mNext.read(nif);
recordSize = nif->getUInt(); 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. // An extra data record. All the extra data connected to an object form a linked list.
struct Extra : public Record struct Extra : public Record
{ {
std::string name; std::string mName;
ExtraPtr next; // Next extra data record in the list ExtraPtr mNext; // Next extra data record in the list
unsigned int recordSize{ 0u }; uint32_t mRecordSize{ 0u };
void read(NIFStream* nif) override; 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 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 "controller.hpp"
#include "controlled.hpp"
#include "data.hpp" #include "data.hpp"
#include "node.hpp" #include "node.hpp"
#include "recordptr.hpp" #include "particle.hpp"
#include "texture.hpp"
namespace Nif namespace Nif
{ {

View File

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

View File

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

View File

@ -6,25 +6,21 @@ namespace Nif
void NiExtraData::read(NIFStream* nif) void NiExtraData::read(NIFStream* nif)
{ {
Extra::read(nif); Extra::read(nif);
nif->readVector(data, recordSize);
}
void NiStringExtraData::read(NIFStream* nif) nif->readVector(mData, mRecordSize);
{
Extra::read(nif);
string = nif->getString();
} }
void NiTextKeyExtraData::read(NIFStream* nif) void NiTextKeyExtraData::read(NIFStream* nif)
{ {
Extra::read(nif); Extra::read(nif);
int keynum = nif->getInt(); uint32_t numKeys;
list.resize(keynum); nif->read(numKeys);
for (int i = 0; i < keynum; i++) mList.resize(numKeys);
for (TextKey& key : mList)
{ {
list[i].time = nif->getFloat(); nif->read(key.mTime);
list[i].text = nif->getString(); nif->read(key.mText);
} }
} }
@ -32,81 +28,39 @@ namespace Nif
{ {
Extra::read(nif); Extra::read(nif);
nif->skip(nif->getUShort() * sizeof(float)); // vertex weights I guess nif->skip(nif->get<uint16_t>() * 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());
} }
void BSBound::read(NIFStream* nif) void BSBound::read(NIFStream* nif)
{ {
Extra::read(nif); Extra::read(nif);
center = nif->getVector3();
halfExtents = nif->getVector3(); nif->read(mCenter);
nif->read(mExtents);
} }
void BSFurnitureMarker::LegacyFurniturePosition::read(NIFStream* nif) void BSFurnitureMarker::LegacyFurniturePosition::read(NIFStream* nif)
{ {
mOffset = nif->getVector3(); nif->read(mOffset);
mOrientation = nif->getUShort(); nif->read(mOrientation);
mPositionRef = nif->getChar(); nif->read(mPositionRef);
nif->skip(1); // Position ref 2 nif->skip(1); // Position ref 2
} }
void BSFurnitureMarker::FurniturePosition::read(NIFStream* nif) void BSFurnitureMarker::FurniturePosition::read(NIFStream* nif)
{ {
mOffset = nif->getVector3(); nif->read(mOffset);
mHeading = nif->getFloat(); nif->read(mHeading);
mType = nif->getUShort(); nif->read(mType);
mEntryPoint = nif->getUShort(); nif->read(mEntryPoint);
} }
void BSFurnitureMarker::read(NIFStream* nif) void BSFurnitureMarker::read(NIFStream* nif)
{ {
Extra::read(nif); Extra::read(nif);
unsigned int num = nif->getUInt();
uint32_t num;
nif->read(num);
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
{ {
mLegacyMarkers.resize(num); mLegacyMarkers.resize(num);
@ -124,19 +78,20 @@ namespace Nif
void BSInvMarker::read(NIFStream* nif) void BSInvMarker::read(NIFStream* nif)
{ {
Extra::read(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); mRotation = osg::Quat(rotX, osg::X_AXIS, rotY, osg::Y_AXIS, rotZ, osg::Z_AXIS);
nif->read(mScale);
} }
void BSBehaviorGraphExtraData::read(NIFStream* nif) void BSBehaviorGraphExtraData::read(NIFStream* nif)
{ {
Extra::read(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 #ifndef OPENMW_COMPONENTS_NIF_EXTRA_HPP
#define OPENMW_COMPONENTS_NIF_EXTRA_HPP #define OPENMW_COMPONENTS_NIF_EXTRA_HPP
@ -29,9 +6,46 @@
namespace Nif 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 struct NiExtraData : public Extra
{ {
std::vector<char> data; std::vector<uint8_t> mData;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
@ -45,78 +59,17 @@ namespace Nif
{ {
struct TextKey struct TextKey
{ {
float time; float mTime;
std::string text; std::string mText;
}; };
std::vector<TextKey> list; std::vector<TextKey> mList;
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;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
struct BSBound : public Extra struct BSBound : public Extra
{ {
osg::Vec3f center, halfExtents; osg::Vec3f mCenter, mExtents;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
@ -149,7 +102,7 @@ namespace Nif
struct BSInvMarker : public Extra struct BSInvMarker : public Extra
{ {
osg::Quat mRotation; osg::Quat mRotation;
float mScale = 1.0f; float mScale;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
@ -162,5 +115,5 @@ namespace Nif
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
} // Namespace }
#endif #endif

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#include "property.hpp" #include "property.hpp"
#include "controlled.hpp"
#include "data.hpp" #include "data.hpp"
#include "texture.hpp"
namespace Nif 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 // Check for extra data
std::vector<Nif::ExtraPtr> extraCollection; 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); extraCollection.emplace_back(e);
for (const auto& extraNode : node.extralist) for (const auto& extraNode : node.extralist)
if (!extraNode.empty()) if (!extraNode.empty())
@ -316,29 +316,30 @@ namespace NifBullet
{ {
// String markers may contain important information // String markers may contain important information
// affecting the entire subtree of this node // 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 // NCC flag in vanilla is partly case sensitive: prefix NC is case insensitive but second C needs be
// uppercase // uppercase
if (sd->string.length() > 2 && sd->string[2] == 'C') if (sd->mData.length() > 2 && sd->mData[2] == 'C')
// Collide only with camera. // Collide only with camera.
visualCollisionType = Resource::VisualCollisionType::Camera; visualCollisionType = Resource::VisualCollisionType::Camera;
else else
// No collision. // No collision.
visualCollisionType = Resource::VisualCollisionType::Default; 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; return;
} }
} }
else if (e->recType == Nif::RC_BSXFlags) else if (e->recType == Nif::RC_BSXFlags)
{ {
auto bsxFlags = static_cast<const Nif::NiIntegerExtraData*>(e.getPtr()); 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; args.mHasMarkers = true;
} }
} }

View File

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

View File

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

View File

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