forked from teamnwah/openmw-tes3coop
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);
|
NiDynamicEffect::read(nif);
|
||||||
|
|
||||||
/*
|
// Model Projection Matrix
|
||||||
3 x Vector4 = [1,0,0,0]
|
nif->skip(3 * 3 * sizeof(float));
|
||||||
int = 2
|
|
||||||
int = 0 or 3
|
// Model Projection Transform
|
||||||
int = 2
|
nif->skip(3 * sizeof(float));
|
||||||
int = 2
|
|
||||||
*/
|
// Texture Filtering
|
||||||
nif->skip(16*4);
|
nif->skip(4);
|
||||||
|
|
||||||
|
clamp = nif->getUInt();
|
||||||
|
|
||||||
|
textureType = (TextureType)nif->getUInt();
|
||||||
|
|
||||||
|
coordGenType = (CoordGenType)nif->getUInt();
|
||||||
|
|
||||||
texture.read(nif);
|
texture.read(nif);
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,26 @@ struct NiSpotLight : public NiPointLight
|
||||||
struct NiTextureEffect : NiDynamicEffect
|
struct NiTextureEffect : NiDynamicEffect
|
||||||
{
|
{
|
||||||
NiSourceTexturePtr texture;
|
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 read(NIFStream *nif);
|
||||||
void post(NIFFile *nif);
|
void post(NIFFile *nif);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
#include <osg/Array>
|
#include <osg/Array>
|
||||||
#include <osg/LOD>
|
#include <osg/LOD>
|
||||||
|
#include <osg/TexGen>
|
||||||
|
|
||||||
// resource
|
// resource
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
#include <osg/TexEnvCombine>
|
#include <osg/TexEnvCombine>
|
||||||
|
|
||||||
#include <components/nif/node.hpp>
|
#include <components/nif/node.hpp>
|
||||||
|
#include <components/nif/effect.hpp>
|
||||||
#include <components/sceneutil/util.hpp>
|
#include <components/sceneutil/util.hpp>
|
||||||
#include <components/sceneutil/skeleton.hpp>
|
#include <components/sceneutil/skeleton.hpp>
|
||||||
#include <components/sceneutil/riggeometry.hpp>
|
#include <components/sceneutil/riggeometry.hpp>
|
||||||
|
@ -439,6 +441,81 @@ namespace NifOsg
|
||||||
return lod;
|
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,
|
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)
|
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);
|
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
|
||||||
if(ninode)
|
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;
|
const Nif::NodeList &children = ninode->children;
|
||||||
for(size_t i = 0;i < children.length();++i)
|
for(size_t i = 0;i < children.length();++i)
|
||||||
{
|
{
|
||||||
if(!children[i].empty())
|
if(!children[i].empty())
|
||||||
{
|
|
||||||
handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, particleflags, skipMeshes, textKeys, rootNode);
|
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);
|
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(handleSourceTexture(st.getPtr(), imageManager)));
|
||||||
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D(imageManager->getImage(filename)));
|
|
||||||
texture->setWrap(osg::Texture::WRAP_S, wrapS);
|
texture->setWrap(osg::Texture::WRAP_S, wrapS);
|
||||||
texture->setWrap(osg::Texture::WRAP_T, wrapT);
|
texture->setWrap(osg::Texture::WRAP_T, wrapT);
|
||||||
textures.push_back(texture);
|
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;
|
std::cerr << "Warning: texture layer " << i << " is in use but empty in " << mFilename << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
osg::ref_ptr<osg::Image> image;
|
|
||||||
const Nif::NiSourceTexture *st = tex.texture.getPtr();
|
const Nif::NiSourceTexture *st = tex.texture.getPtr();
|
||||||
if (!st->external && !st->data.empty())
|
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager);
|
||||||
{
|
|
||||||
image = handleInternalTexture(st->data.getPtr());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, imageManager->getVFS());
|
|
||||||
image = imageManager->getImage(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int clamp = static_cast<unsigned int>(tex.clamp);
|
unsigned int clamp = static_cast<unsigned int>(tex.clamp);
|
||||||
int wrapT = (clamp) & 0x1;
|
int wrapT = (clamp) & 0x1;
|
||||||
|
|
Loading…
Reference in a new issue