forked from mirror/openmw-tes3mp
Implement support for sphere map NiTextureEffects (Fixes #1827)
This commit is contained in:
parent
01497ac8db
commit
5f4ace1bc2
3 changed files with 120 additions and 22 deletions
|
@ -19,14 +19,20 @@ void NiTextureEffect::read(NIFStream *nif)
|
|||
{
|
||||
NiDynamicEffect::read(nif);
|
||||
|
||||
/*
|
||||
3 x Vector4 = [1,0,0,0]
|
||||
int = 2
|
||||
int = 0 or 3
|
||||
int = 2
|
||||
int = 2
|
||||
*/
|
||||
nif->skip(16*4);
|
||||
// Model Projection Matrix
|
||||
nif->skip(3 * 3 * sizeof(float));
|
||||
|
||||
// Model Projection Transform
|
||||
nif->skip(3 * sizeof(float));
|
||||
|
||||
// Texture Filtering
|
||||
nif->skip(4);
|
||||
|
||||
clamp = nif->getUInt();
|
||||
|
||||
textureType = (TextureType)nif->getUInt();
|
||||
|
||||
coordGenType = (CoordGenType)nif->getUInt();
|
||||
|
||||
texture.read(nif);
|
||||
|
||||
|
|
|
@ -70,6 +70,26 @@ struct NiSpotLight : public NiPointLight
|
|||
struct NiTextureEffect : NiDynamicEffect
|
||||
{
|
||||
NiSourceTexturePtr texture;
|
||||
unsigned int clamp;
|
||||
|
||||
enum TextureType
|
||||
{
|
||||
Projected_Light = 0,
|
||||
Projected_Shadow = 1,
|
||||
Environment_Map = 2,
|
||||
Fog_Map = 3
|
||||
};
|
||||
TextureType textureType;
|
||||
|
||||
enum CoordGenType
|
||||
{
|
||||
World_Parallel = 0,
|
||||
World_Perspective,
|
||||
Sphere_Map,
|
||||
Specular_Cube_Map,
|
||||
Diffuse_Cube_Map
|
||||
};
|
||||
CoordGenType coordGenType;
|
||||
|
||||
void read(NIFStream *nif);
|
||||
void post(NIFFile *nif);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <osg/Geometry>
|
||||
#include <osg/Array>
|
||||
#include <osg/LOD>
|
||||
#include <osg/TexGen>
|
||||
|
||||
// resource
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include <osg/TexEnvCombine>
|
||||
|
||||
#include <components/nif/node.hpp>
|
||||
#include <components/nif/effect.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
#include <components/sceneutil/skeleton.hpp>
|
||||
#include <components/sceneutil/riggeometry.hpp>
|
||||
|
@ -439,6 +441,81 @@ namespace NifOsg
|
|||
return lod;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Image> handleSourceTexture(const Nif::NiSourceTexture* st, Resource::ImageManager* imageManager)
|
||||
{
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
osg::ref_ptr<osg::Image> image;
|
||||
if (!st->external && !st->data.empty())
|
||||
{
|
||||
image = handleInternalTexture(st->data.getPtr());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, imageManager->getVFS());
|
||||
image = imageManager->getImage(filename);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
void handleEffect(const Nif::Node* nifNode, osg::Node* node, Resource::ImageManager* imageManager)
|
||||
{
|
||||
if (nifNode->recType != Nif::RC_NiTextureEffect)
|
||||
{
|
||||
std::cerr << "Unhandled effect " << nifNode->recName << " in " << mFilename << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
const Nif::NiTextureEffect* textureEffect = static_cast<const Nif::NiTextureEffect*>(nifNode);
|
||||
if (textureEffect->textureType != Nif::NiTextureEffect::Environment_Map)
|
||||
{
|
||||
std::cerr << "Unhandled NiTextureEffect type " << textureEffect->textureType << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::TexGen> texGen (new osg::TexGen);
|
||||
switch (textureEffect->coordGenType)
|
||||
{
|
||||
case Nif::NiTextureEffect::World_Parallel:
|
||||
texGen->setMode(osg::TexGen::OBJECT_LINEAR);
|
||||
break;
|
||||
case Nif::NiTextureEffect::World_Perspective:
|
||||
texGen->setMode(osg::TexGen::EYE_LINEAR);
|
||||
break;
|
||||
case Nif::NiTextureEffect::Sphere_Map:
|
||||
texGen->setMode(osg::TexGen::SPHERE_MAP);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unhandled NiTextureEffect coordGenType " << textureEffect->coordGenType << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> texture2d (new osg::Texture2D(handleSourceTexture(textureEffect->texture.getPtr(), imageManager)));
|
||||
texture2d->setName("envMap");
|
||||
unsigned int clamp = static_cast<unsigned int>(textureEffect->clamp);
|
||||
int wrapT = (clamp) & 0x1;
|
||||
int wrapS = (clamp >> 1) & 0x1;
|
||||
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
||||
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
||||
|
||||
osg::ref_ptr<osg::TexEnvCombine> texEnv = new osg::TexEnvCombine;
|
||||
texEnv->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
|
||||
texEnv->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
|
||||
texEnv->setCombine_RGB(osg::TexEnvCombine::ADD);
|
||||
texEnv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
|
||||
texEnv->setSource1_RGB(osg::TexEnvCombine::TEXTURE);
|
||||
|
||||
int texUnit = 3; // FIXME
|
||||
|
||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
|
||||
stateset->setTextureAttributeAndModes(texUnit, texGen, osg::StateAttribute::ON);
|
||||
stateset->setTextureAttributeAndModes(texUnit, texEnv, osg::StateAttribute::ON);
|
||||
|
||||
stateset->addUniform(new osg::Uniform("envMapColor", osg::Vec4f(1,1,1,1)));
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
||||
std::vector<int> boundTextures, int animflags, int particleflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL)
|
||||
{
|
||||
|
@ -582,13 +659,18 @@ namespace NifOsg
|
|||
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
|
||||
if(ninode)
|
||||
{
|
||||
const Nif::NodeList &effects = ninode->effects;
|
||||
for (size_t i = 0; i < effects.length(); ++i)
|
||||
{
|
||||
if (!effects[i].empty())
|
||||
handleEffect(effects[i].getPtr(), node, imageManager);
|
||||
}
|
||||
|
||||
const Nif::NodeList &children = ninode->children;
|
||||
for(size_t i = 0;i < children.length();++i)
|
||||
{
|
||||
if(!children[i].empty())
|
||||
{
|
||||
handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, particleflags, skipMeshes, textKeys, rootNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,8 +789,7 @@ namespace NifOsg
|
|||
wrapT = inherit->getWrap(osg::Texture2D::WRAP_T);
|
||||
}
|
||||
|
||||
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, imageManager->getVFS());
|
||||
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D(imageManager->getImage(filename)));
|
||||
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D(handleSourceTexture(st.getPtr(), imageManager)));
|
||||
texture->setWrap(osg::Texture::WRAP_S, wrapS);
|
||||
texture->setWrap(osg::Texture::WRAP_T, wrapT);
|
||||
textures.push_back(texture);
|
||||
|
@ -1318,17 +1399,8 @@ namespace NifOsg
|
|||
std::cerr << "Warning: texture layer " << i << " is in use but empty in " << mFilename << std::endl;
|
||||
continue;
|
||||
}
|
||||
osg::ref_ptr<osg::Image> image;
|
||||
const Nif::NiSourceTexture *st = tex.texture.getPtr();
|
||||
if (!st->external && !st->data.empty())
|
||||
{
|
||||
image = handleInternalTexture(st->data.getPtr());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, imageManager->getVFS());
|
||||
image = imageManager->getImage(filename);
|
||||
}
|
||||
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager);
|
||||
|
||||
unsigned int clamp = static_cast<unsigned int>(tex.clamp);
|
||||
int wrapT = (clamp) & 0x1;
|
||||
|
|
Loading…
Reference in a new issue