You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/apps/components_tests/nifosg/testnifloader.cpp

304 lines
8.5 KiB
C++

#include "../nif/node.hpp"
#include <components/nif/node.hpp>
#include <components/nif/property.hpp>
#include <components/nifosg/nifloader.hpp>
#include <components/resource/bgsmfilemanager.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/sceneutil/serialize.hpp>
#include <components/vfs/manager.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <osgDB/Registry>
#include <array>
#include <limits>
#include <sstream>
#include <stdexcept>
#include <string>
#include <string_view>
namespace
{
using namespace testing;
using namespace NifOsg;
using namespace Nif::Testing;
constexpr VFS::Path::NormalizedView testNif("test.nif");
struct BaseNifOsgLoaderTest
{
VFS::Manager mVfs;
Resource::ImageManager mImageManager{ &mVfs, 0 };
Resource::BgsmFileManager mMaterialManager{ &mVfs, 0 };
const osgDB::ReaderWriter* mReaderWriter = osgDB::Registry::instance()->getReaderWriterForExtension("osgt");
osg::ref_ptr<osgDB::Options> mOptions = new osgDB::Options;
BaseNifOsgLoaderTest()
{
SceneUtil::registerSerializers();
if (mReaderWriter == nullptr)
throw std::runtime_error("osgt reader writer is not found");
mOptions->setPluginStringData("fileType", "Ascii");
mOptions->setPluginStringData("WriteImageHint", "UseExternal");
}
std::string serialize(const osg::Node& node) const
{
std::stringstream stream;
mReaderWriter->writeNode(node, stream, mOptions);
std::string result;
for (std::string line; std::getline(stream, line);)
{
if (line.starts_with('#'))
continue;
line.erase(line.find_last_not_of(" \t\n\r\f\v") + 1);
result += line;
result += '\n';
}
return result;
}
};
struct NifOsgLoaderTest : Test, BaseNifOsgLoaderTest
{
};
TEST_F(NifOsgLoaderTest, shouldLoadFileWithDefaultNode)
{
Nif::NiAVObject node;
init(node);
Nif::NIFFile file(testNif);
file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager, &mMaterialManager);
EXPECT_EQ(serialize(*result), R"(
osg::Group {
UniqueID 1
DataVariance STATIC
UserDataContainer TRUE {
osg::DefaultUserDataContainer {
UniqueID 2
UDC_UserObjects 1 {
osg::StringValueObject {
UniqueID 3
Name "fileHash"
}
}
}
}
Children 1 {
osg::Group {
UniqueID 4
DataVariance STATIC
UserDataContainer TRUE {
osg::DefaultUserDataContainer {
UniqueID 5
UDC_UserObjects 1 {
osg::UIntValueObject {
UniqueID 6
Name "recIndex"
Value 4294967295
}
}
}
}
}
}
}
)");
}
std::string formatOsgNodeForBSShaderProperty(std::string_view shaderPrefix)
{
std::ostringstream oss;
oss << R"(
osg::Group {
UniqueID 1
DataVariance STATIC
UserDataContainer TRUE {
osg::DefaultUserDataContainer {
UniqueID 2
UDC_UserObjects 1 {
osg::StringValueObject {
UniqueID 3
Name "fileHash"
}
}
}
}
Children 1 {
osg::Group {
UniqueID 4
DataVariance STATIC
UserDataContainer TRUE {
osg::DefaultUserDataContainer {
UniqueID 5
UDC_UserObjects 3 {
osg::UIntValueObject {
UniqueID 6
Name "recIndex"
Value 4294967295
}
osg::StringValueObject {
UniqueID 7
Name "shaderPrefix"
Value ")"
<< shaderPrefix << R"("
}
osg::BoolValueObject {
UniqueID 8
Name "shaderRequired"
Value TRUE
}
}
}
}
StateSet TRUE {
osg::StateSet {
UniqueID 9
}
}
}
}
}
)";
return oss.str();
}
std::string formatOsgNodeForBSLightingShaderProperty(std::string_view shaderPrefix)
{
std::ostringstream oss;
oss << R"(
osg::Group {
UniqueID 1
DataVariance STATIC
UserDataContainer TRUE {
osg::DefaultUserDataContainer {
UniqueID 2
UDC_UserObjects 1 {
osg::StringValueObject {
UniqueID 3
Name "fileHash"
}
}
}
}
Children 1 {
osg::Group {
UniqueID 4
DataVariance STATIC
UserDataContainer TRUE {
osg::DefaultUserDataContainer {
UniqueID 5
UDC_UserObjects 3 {
osg::UIntValueObject {
UniqueID 6
Name "recIndex"
Value 4294967295
}
osg::StringValueObject {
UniqueID 7
Name "shaderPrefix"
Value ")"
<< shaderPrefix << R"("
}
osg::BoolValueObject {
UniqueID 8
Name "shaderRequired"
Value TRUE
}
}
}
}
StateSet TRUE {
osg::StateSet {
UniqueID 9
ModeList 1 {
GL_DEPTH_TEST ON
}
AttributeList 1 {
osg::Depth {
UniqueID 10
Function LEQUAL
}
Value OFF
}
}
}
}
}
}
)";
return oss.str();
}
struct ShaderPrefixParams
{
unsigned int mShaderType;
std::string_view mExpectedShaderPrefix;
};
struct NifOsgLoaderBSShaderPrefixTest : TestWithParam<ShaderPrefixParams>, BaseNifOsgLoaderTest
{
static constexpr std::array sParams = {
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Default), "bs/default" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_NoLighting), "bs/nolighting" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Tile), "bs/default" },
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "bs/default" },
};
};
TEST_P(NifOsgLoaderBSShaderPrefixTest, shouldAddShaderPrefix)
{
Nif::NiAVObject node;
init(node);
Nif::BSShaderPPLightingProperty property;
property.recType = Nif::RC_BSShaderPPLightingProperty;
property.mTextureSet = nullptr;
property.mController = nullptr;
property.mType = GetParam().mShaderType;
node.mProperties.push_back(Nif::RecordPtrT<Nif::NiProperty>(&property));
Nif::NIFFile file(testNif);
file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager, &mMaterialManager);
EXPECT_EQ(serialize(*result), formatOsgNodeForBSShaderProperty(GetParam().mExpectedShaderPrefix));
}
INSTANTIATE_TEST_SUITE_P(Params, NifOsgLoaderBSShaderPrefixTest, ValuesIn(NifOsgLoaderBSShaderPrefixTest::sParams));
struct NifOsgLoaderBSLightingShaderPrefixTest : TestWithParam<ShaderPrefixParams>, BaseNifOsgLoaderTest
{
static constexpr std::array sParams = {
ShaderPrefixParams{
static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Default), "bs/default" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Cloud), "bs/default" },
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "bs/default" },
};
};
TEST_P(NifOsgLoaderBSLightingShaderPrefixTest, shouldAddShaderPrefix)
{
Nif::NiAVObject node;
init(node);
Nif::BSLightingShaderProperty property;
property.recType = Nif::RC_BSLightingShaderProperty;
property.mTextureSet = nullptr;
property.mController = nullptr;
property.mType = GetParam().mShaderType;
property.mShaderFlags1 |= Nif::BSShaderFlags1::BSSFlag1_DepthTest;
property.mShaderFlags2 |= Nif::BSShaderFlags2::BSSFlag2_DepthWrite;
node.mProperties.push_back(Nif::RecordPtrT<Nif::NiProperty>(&property));
Nif::NIFFile file(testNif);
file.mRoots.push_back(&node);
auto result = Loader::load(file, &mImageManager, &mMaterialManager);
EXPECT_EQ(serialize(*result), formatOsgNodeForBSLightingShaderProperty(GetParam().mExpectedShaderPrefix));
}
INSTANTIATE_TEST_SUITE_P(
Params, NifOsgLoaderBSLightingShaderPrefixTest, ValuesIn(NifOsgLoaderBSLightingShaderPrefixTest::sParams));
}