Extremely early handling for BGSM/BGEM files

master
Alexei Kotov 3 weeks ago
parent fe1cb3a5ae
commit 1a961f3021

@ -12,6 +12,7 @@
#include <components/files/multidircollection.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/platform/platform.hpp>
#include <components/resource/bgsmfilemanager.hpp>
#include <components/resource/bulletshape.hpp>
#include <components/resource/bulletshapemanager.hpp>
#include <components/resource/foreachbulletobject.hpp>
@ -173,7 +174,8 @@ namespace
constexpr double expiryDelay = 0;
Resource::ImageManager imageManager(&vfs, expiryDelay);
Resource::NifFileManager nifFileManager(&vfs, &encoder.getStatelessEncoder());
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, expiryDelay);
Resource::BgsmFileManager bgsmFileManager(&vfs, expiryDelay);
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, &bgsmFileManager, expiryDelay);
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager, expiryDelay);
Resource::forEachBulletObject(

@ -19,6 +19,7 @@
#include <components/files/conversion.hpp>
#include <components/files/multidircollection.hpp>
#include <components/platform/platform.hpp>
#include <components/resource/bgsmfilemanager.hpp>
#include <components/resource/bulletshapemanager.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/resource/niffilemanager.hpp>
@ -220,7 +221,8 @@ namespace NavMeshTool
Resource::ImageManager imageManager(&vfs, expiryDelay);
Resource::NifFileManager nifFileManager(&vfs, &encoder.getStatelessEncoder());
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, expiryDelay);
Resource::BgsmFileManager bgsmFileManager(&vfs, expiryDelay);
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, &bgsmFileManager, expiryDelay);
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager, expiryDelay);
DetourNavigator::RecastGlobalAllocator::init();
DetourNavigator::Settings navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();

@ -70,7 +70,7 @@ namespace
init(node);
Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager);
auto result = Loader::load(file, &mImageManager, nullptr);
EXPECT_EQ(serialize(*result), R"(
osg::Group {
UniqueID 1
@ -259,7 +259,7 @@ osg::Group {
node.mProperties.push_back(Nif::RecordPtrT<Nif::NiProperty>(&property));
Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager);
auto result = Loader::load(file, &mImageManager, nullptr);
EXPECT_EQ(serialize(*result), formatOsgNodeForBSShaderProperty(GetParam().mExpectedShaderPrefix));
}
@ -289,7 +289,7 @@ osg::Group {
node.mProperties.push_back(Nif::RecordPtrT<Nif::NiProperty>(&property));
Nif::NIFFile file("test.nif");
file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager);
auto result = Loader::load(file, &mImageManager, nullptr);
EXPECT_EQ(serialize(*result), formatOsgNodeForBSLightingShaderProperty(GetParam().mExpectedShaderPrefix));
}

@ -173,6 +173,11 @@ std::string Misc::ResourceHelpers::correctActorModelPath(const std::string& resP
return mdlname;
}
std::string Misc::ResourceHelpers::correctMaterialPath(std::string_view resPath, const VFS::Manager* vfs)
{
return correctResourcePath({ { "materials" } }, resPath, vfs);
}
std::string Misc::ResourceHelpers::correctMeshPath(std::string_view resPath)
{
std::string res = "meshes\\";

@ -34,6 +34,7 @@ namespace Misc
/// Use "xfoo.nif" instead of "foo.nif" if "xfoo.kf" is available
/// Note that if "xfoo.nif" is actually unavailable, we can't fall back to "foo.nif". :(
std::string correctActorModelPath(const std::string& resPath, const VFS::Manager* vfs);
std::string correctMaterialPath(std::string_view resPath, const VFS::Manager* vfs);
// Adds "meshes\\".
std::string correctMeshPath(std::string_view resPath);

@ -21,6 +21,7 @@
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/lower.hpp>
#include <components/nif/parent.hpp>
#include <components/resource/bgsmfilemanager.hpp>
#include <components/resource/imagemanager.hpp>
// particle
@ -42,6 +43,7 @@
#include <osg/TexEnvCombine>
#include <osg/Texture2D>
#include <components/bgsm/file.hpp>
#include <components/nif/effect.hpp>
#include <components/nif/exception.hpp>
#include <components/nif/extra.hpp>
@ -238,15 +240,17 @@ namespace NifOsg
{
public:
/// @param filename used for warning messages.
LoaderImpl(const std::filesystem::path& filename, unsigned int ver, unsigned int userver, unsigned int bethver)
LoaderImpl(const std::filesystem::path& filename, unsigned int ver, unsigned int userver, unsigned int bethver, Resource::BgsmFileManager* materialMgr)
: mFilename(filename)
, mVersion(ver)
, mUserVersion(userver)
, mBethVersion(bethver)
, mMaterialMgr(materialMgr)
{
}
std::filesystem::path mFilename;
unsigned int mVersion, mUserVersion, mBethVersion;
Resource::BgsmFileManager* mMaterialMgr;
size_t mFirstRootTextureIndex{ ~0u };
bool mFoundFirstRootTexturingProperty = false;
@ -2155,6 +2159,98 @@ namespace NifOsg
handleTextureControllers(texprop, composite, imageManager, stateset, animflags);
}
void handleShaderMaterial(const std::string& path, osg::StateSet* stateset, Resource::ImageManager* imageManager,
std::vector<unsigned int>& boundTextures)
{
if (!mMaterialMgr)
return;
Bgsm::MaterialFilePtr material = mMaterialMgr->get(VFS::Path::Normalized(path));
if (!material)
return;
if (material->mShaderType == Bgsm::ShaderType::Lighting)
{
const Bgsm::BGSMFile* bgsm = static_cast<const Bgsm::BGSMFile*>(material.get());
if (!boundTextures.empty())
{
for (unsigned int i = 0; i < boundTextures.size(); ++i)
stateset->setTextureMode(i, GL_TEXTURE_2D, osg::StateAttribute::OFF);
boundTextures.clear();
}
const unsigned int uvSet = 0;
if (!bgsm->mDiffuseMap.empty())
{
std::string filename
= Misc::ResourceHelpers::correctTexturePath(bgsm->mDiffuseMap, imageManager->getVFS());
osg::ref_ptr<osg::Image> image = imageManager->getImage(filename);
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
if (image)
texture2d->setTextureSize(image->s(), image->t());
handleTextureWrapping(texture2d, (bgsm->mClamp >> 1) & 0x1, bgsm->mClamp & 0x1);
unsigned int texUnit = boundTextures.size();
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
texture2d->setName("diffuseMap");
boundTextures.emplace_back(uvSet);
}
if (!bgsm->mNormalMap.empty())
{
std::string filename
= Misc::ResourceHelpers::correctTexturePath(bgsm->mNormalMap, imageManager->getVFS());
osg::ref_ptr<osg::Image> image = imageManager->getImage(filename);
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
if (image)
texture2d->setTextureSize(image->s(), image->t());
handleTextureWrapping(texture2d, (bgsm->mClamp >> 1) & 0x1, bgsm->mClamp & 0x1);
unsigned int texUnit = boundTextures.size();
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
texture2d->setName("normalMap");
boundTextures.emplace_back(uvSet);
}
if (bgsm->mTwoSided)
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
if (bgsm->mTree)
stateset->addUniform(new osg::Uniform("useTreeAnim", true));
handleDepthFlags(stateset, bgsm->mDepthTest, bgsm->mDepthWrite);
}
else
{
const Bgsm::BGEMFile* bgem = static_cast<const Bgsm::BGEMFile*>(material.get());
if (!bgem->mBaseMap.empty())
{
if (!boundTextures.empty())
{
for (unsigned int i = 0; i < boundTextures.size(); ++i)
stateset->setTextureMode(i, GL_TEXTURE_2D, osg::StateAttribute::OFF);
boundTextures.clear();
}
std::string filename = Misc::ResourceHelpers::correctTexturePath(
bgem->mBaseMap, imageManager->getVFS());
osg::ref_ptr<osg::Image> image = imageManager->getImage(filename);
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
texture2d->setName("diffuseMap");
if (image)
texture2d->setTextureSize(image->s(), image->t());
handleTextureWrapping(texture2d, (bgem->mClamp >> 1) & 0x1, bgem->mClamp & 0x1);
const unsigned int texUnit = 0;
const unsigned int uvSet = 0;
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
boundTextures.push_back(uvSet);
}
bool useFalloff = bgem->mFalloff;
stateset->addUniform(new osg::Uniform("useFalloff", useFalloff));
if (useFalloff)
stateset->addUniform(new osg::Uniform("falloffParams", bgem->mFalloffParams));
handleDepthFlags(stateset, bgem->mDepthTest, bgem->mDepthWrite);
}
}
void handleTextureSet(const Nif::BSShaderTextureSet* textureSet, unsigned int clamp,
const std::string& nodeName, osg::StateSet* stateset, Resource::ImageManager* imageManager,
std::vector<unsigned int>& boundTextures)
@ -2421,6 +2517,12 @@ namespace NifOsg
node->setUserValue("shaderPrefix", std::string(getBSLightingShaderPrefix(texprop->mType)));
node->setUserValue("shaderRequired", shaderRequired);
osg::StateSet* stateset = node->getOrCreateStateSet();
std::string normalizedName = Misc::ResourceHelpers::correctMaterialPath(texprop->mName, mMaterialMgr->getVFS());
if (normalizedName.ends_with(".bgsm"))
{
handleShaderMaterial(normalizedName, stateset, imageManager, boundTextures);
break;
}
if (!texprop->mTextureSet.empty())
handleTextureSet(texprop->mTextureSet.getPtr(), texprop->mClamp, node->getName(), stateset,
imageManager, boundTextures);
@ -2442,6 +2544,12 @@ namespace NifOsg
node->setUserValue("shaderPrefix", std::string("bs/nolighting"));
node->setUserValue("shaderRequired", shaderRequired);
osg::StateSet* stateset = node->getOrCreateStateSet();
std::string normalizedName = Misc::ResourceHelpers::correctMaterialPath(texprop->mName, mMaterialMgr->getVFS());
if (normalizedName.ends_with(".bgem"))
{
handleShaderMaterial(normalizedName, stateset, imageManager, boundTextures);
break;
}
if (!texprop->mSourceTexture.empty())
{
if (!boundTextures.empty())
@ -2860,15 +2968,15 @@ namespace NifOsg
}
};
osg::ref_ptr<osg::Node> Loader::load(Nif::FileView file, Resource::ImageManager* imageManager)
osg::ref_ptr<osg::Node> Loader::load(Nif::FileView file, Resource::ImageManager* imageManager, Resource::BgsmFileManager* materialMgr)
{
LoaderImpl impl(file.getFilename(), file.getVersion(), file.getUserVersion(), file.getBethVersion());
LoaderImpl impl(file.getFilename(), file.getVersion(), file.getUserVersion(), file.getBethVersion(), materialMgr);
return impl.load(file, imageManager);
}
void Loader::loadKf(Nif::FileView kf, SceneUtil::KeyframeHolder& target)
{
LoaderImpl impl(kf.getFilename(), kf.getVersion(), kf.getUserVersion(), kf.getBethVersion());
LoaderImpl impl(kf.getFilename(), kf.getVersion(), kf.getUserVersion(), kf.getBethVersion(), nullptr);
impl.loadKf(kf, target);
}

@ -18,6 +18,7 @@ namespace osg
namespace Resource
{
class ImageManager;
class BgsmFileManager;
}
namespace NifOsg
@ -30,7 +31,7 @@ namespace NifOsg
public:
/// Create a scene graph for the given NIF. Auto-detects when skinning is used and wraps the graph in a Skeleton
/// if so.
static osg::ref_ptr<osg::Node> load(Nif::FileView file, Resource::ImageManager* imageManager);
static osg::ref_ptr<osg::Node> load(Nif::FileView file, Resource::ImageManager* imageManager, Resource::BgsmFileManager* materialManager);
/// Load keyframe controllers from the given kf file.
static void loadKf(Nif::FileView kf, SceneUtil::KeyframeHolder& target);

@ -2,6 +2,7 @@
#include <algorithm>
#include "bgsmfilemanager.hpp"
#include "imagemanager.hpp"
#include "keyframemanager.hpp"
#include "niffilemanager.hpp"
@ -15,11 +16,13 @@ namespace Resource
: mVFS(vfs)
{
mNifFileManager = std::make_unique<NifFileManager>(vfs, encoder);
mBgsmFileManager = std::make_unique<BgsmFileManager>(vfs, expiryDelay);
mImageManager = std::make_unique<ImageManager>(vfs, expiryDelay);
mSceneManager = std::make_unique<SceneManager>(vfs, mImageManager.get(), mNifFileManager.get(), expiryDelay);
mSceneManager = std::make_unique<SceneManager>(vfs, mImageManager.get(), mNifFileManager.get(), mBgsmFileManager.get(), expiryDelay);
mKeyframeManager = std::make_unique<KeyframeManager>(vfs, mSceneManager.get(), expiryDelay, encoder);
addResourceManager(mNifFileManager.get());
addResourceManager(mBgsmFileManager.get());
addResourceManager(mKeyframeManager.get());
// note, scene references images so add images afterwards for correct implementation of updateCache()
addResourceManager(mSceneManager.get());
@ -43,6 +46,11 @@ namespace Resource
return mImageManager.get();
}
BgsmFileManager* ResourceSystem::getBgsmFileManager()
{
return mBgsmFileManager.get();
}
NifFileManager* ResourceSystem::getNifFileManager()
{
return mNifFileManager.get();

@ -25,6 +25,7 @@ namespace Resource
class SceneManager;
class ImageManager;
class BgsmFileManager;
class NifFileManager;
class KeyframeManager;
class BaseResourceManager;
@ -41,6 +42,7 @@ namespace Resource
SceneManager* getSceneManager();
ImageManager* getImageManager();
BgsmFileManager* getBgsmFileManager();
NifFileManager* getNifFileManager();
KeyframeManager* getKeyframeManager();
@ -74,6 +76,7 @@ namespace Resource
private:
std::unique_ptr<SceneManager> mSceneManager;
std::unique_ptr<ImageManager> mImageManager;
std::unique_ptr<BgsmFileManager> mBgsmFileManager;
std::unique_ptr<NifFileManager> mNifFileManager;
std::unique_ptr<KeyframeManager> mKeyframeManager;

@ -55,6 +55,7 @@
#include <components/files/hash.hpp>
#include <components/files/memorystream.hpp>
#include "bgsmfilemanager.hpp"
#include "errormarker.hpp"
#include "imagemanager.hpp"
#include "niffilemanager.hpp"
@ -409,7 +410,7 @@ namespace Resource
};
SceneManager::SceneManager(const VFS::Manager* vfs, Resource::ImageManager* imageManager,
Resource::NifFileManager* nifFileManager, double expiryDelay)
Resource::NifFileManager* nifFileManager, Resource::BgsmFileManager* bgsmFileManager, double expiryDelay)
: ResourceManager(vfs, expiryDelay)
, mShaderManager(new Shader::ShaderManager)
, mForceShaders(false)
@ -424,6 +425,7 @@ namespace Resource
, mSharedStateManager(new SharedStateManager)
, mImageManager(imageManager)
, mNifFileManager(nifFileManager)
, mBgsmFileManager(bgsmFileManager)
, mMinFilter(osg::Texture::LINEAR_MIPMAP_LINEAR)
, mMagFilter(osg::Texture::LINEAR)
, mMaxAnisotropy(1)
@ -795,11 +797,11 @@ namespace Resource
}
osg::ref_ptr<osg::Node> load(VFS::Path::NormalizedView normalizedFilename, const VFS::Manager* vfs,
Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager)
Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager, Resource::BgsmFileManager* materialMgr)
{
const std::string_view ext = Misc::getFileExtension(normalizedFilename.value());
if (ext == "nif")
return NifOsg::Loader::load(*nifFileManager->get(normalizedFilename), imageManager);
return NifOsg::Loader::load(*nifFileManager->get(normalizedFilename), imageManager, materialMgr);
else if (ext == "spt")
{
Log(Debug::Warning) << "Ignoring SpeedTree data file " << normalizedFilename;
@ -921,7 +923,7 @@ namespace Resource
{
path.changeExtension(meshType);
if (mVFS->exists(path))
return load(path, mVFS, mImageManager, mNifFileManager);
return load(path, mVFS, mImageManager, mNifFileManager, mBgsmFileManager);
}
}
catch (const std::exception& e)
@ -953,7 +955,7 @@ namespace Resource
osg::ref_ptr<osg::Node> loaded;
try
{
loaded = load(normalized, mVFS, mImageManager, mNifFileManager);
loaded = load(normalized, mVFS, mImageManager, mNifFileManager, mBgsmFileManager);
SceneUtil::ProcessExtraDataVisitor extraDataVisitor(this);
loaded->accept(extraDataVisitor);

@ -32,6 +32,7 @@ namespace Resource
{
class ImageManager;
class NifFileManager;
class BgsmFileManager;
class SharedStateManager;
}
@ -90,7 +91,7 @@ namespace Resource
{
public:
explicit SceneManager(const VFS::Manager* vfs, Resource::ImageManager* imageManager,
Resource::NifFileManager* nifFileManager, double expiryDelay);
Resource::NifFileManager* nifFileManager, Resource::BgsmFileManager* bgsmFileManager, double expiryDelay);
~SceneManager();
Shader::ShaderManager& getShaderManager();
@ -259,6 +260,7 @@ namespace Resource
Resource::ImageManager* mImageManager;
Resource::NifFileManager* mNifFileManager;
Resource::BgsmFileManager* mBgsmFileManager;
osg::Texture::FilterMode mMinFilter;
osg::Texture::FilterMode mMagFilter;

Loading…
Cancel
Save