#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
+#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
-#include <simgear/math/SGMath.hxx>
#include <simgear/structure/OSGUtils.hxx>
-
-#include "Noise.hxx"
+#include <simgear/props/vectorPropTemplates.hxx>
namespace simgear
{
TexGen* buildTexGen(Effect* Effect, const SGPropertyNode* tgenProp);
// Hack to force inclusion of TextureBuilder.cxx in library
-osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
+osg::Texture* TextureBuilder::buildFromType(Effect* effect, Pass* pass, const string& type,
const SGPropertyNode*props,
const SGReaderWriterOptions*
options)
{
- return EffectBuilder<Texture>::buildFromType(effect, type, props, options);
+ return EffectBuilder<Texture>::buildFromType(effect, pass, type, props, options);
}
typedef boost::tuple<string, Texture::FilterMode, Texture::FilterMode,
type = pType->getStringValue();
Texture* texture = 0;
try {
- texture = TextureBuilder::buildFromType(effect, type, prop,
+ texture = TextureBuilder::buildFromType(effect, pass, type, prop,
options);
}
catch (BuilderException& e) {
- SG_LOG(SG_INPUT, SG_ALERT, e.getFormattedMessage() << ", "
+ SG_LOG(SG_INPUT, SG_DEBUG, e.getFormattedMessage() << ", "
<< "maybe the reader did not set the filename attribute, "
<< "using white for type '" << type << "' on '" << pass->getName() << "', in " << prop->getPath() );
texture = StateAttributeFactory::instance()->getWhiteTexture();
texType, mipmapFunctions);
}
-void setAttrs(const TexTuple& attrs, Texture* tex,
+bool setAttrs(const TexTuple& attrs, Texture* tex,
const SGReaderWriterOptions* options)
{
const string& imageName = attrs.get<0>();
- if (imageName.empty()) {
- throw BuilderException("no image file");
- } else {
- osgDB::ReaderWriter::ReadResult result;
- result = osgDB::readImageFile(imageName, options);
- osg::ref_ptr<osg::Image> image;
- if (result.success())
- image = result.getImage();
- if (image.valid())
- {
- image = computeMipmap( image.get(), attrs.get<7>() );
- tex->setImage(GL_FRONT_AND_BACK, image.get());
- int s = image->s();
- int t = image->t();
- if (s <= t && 32 <= s) {
- SGSceneFeatures::instance()->setTextureCompression(tex);
- } else if (t < s && 32 <= t) {
- SGSceneFeatures::instance()->setTextureCompression(tex);
- }
- tex->setMaxAnisotropy(SGSceneFeatures::instance()
- ->getTextureFilter());
- } else {
- SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file "
- << imageName);
+ if (imageName.empty())
+ return false;
+
+ osgDB::ReaderWriter::ReadResult result;
+ result = osgDB::readImageFile(imageName, options);
+ osg::ref_ptr<osg::Image> image;
+ if (result.success())
+ image = result.getImage();
+ if (image.valid())
+ {
+ image = computeMipmap( image.get(), attrs.get<7>() );
+ tex->setImage(GL_FRONT_AND_BACK, image.get());
+ int s = image->s();
+ int t = image->t();
+ if (s <= t && 32 <= s) {
+ SGSceneFeatures::instance()->setTextureCompression(tex);
+ } else if (t < s && 32 <= t) {
+ SGSceneFeatures::instance()->setTextureCompression(tex);
}
+ tex->setMaxAnisotropy(SGSceneFeatures::instance()
+ ->getTextureFilter());
+ } else {
+ SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file "
+ << imageName);
+ return false;
}
+
// texture->setDataVariance(osg::Object::STATIC);
tex->setFilter(Texture::MIN_FILTER, attrs.get<1>());
tex->setFilter(Texture::MAG_FILTER, attrs.get<2>());
tex->setWrap(Texture::WRAP_S, attrs.get<3>());
tex->setWrap(Texture::WRAP_T, attrs.get<4>());
tex->setWrap(Texture::WRAP_R, attrs.get<5>());
+ return true;
}
-}
+
+} // of anonymous namespace
template<typename T>
class TexBuilder : public TextureBuilder
{
public:
TexBuilder(const string& texType) : _type(texType) {}
- Texture* build(Effect* effect, const SGPropertyNode*,
+ Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
protected:
- typedef map<TexTuple, ref_ptr<T> > TexMap;
+ typedef map<TexTuple, observer_ptr<T> > TexMap;
TexMap texMap;
const string _type;
};
template<typename T>
-Texture* TexBuilder<T>::build(Effect* effect, const SGPropertyNode* props,
+Texture* TexBuilder<T>::build(Effect* effect, Pass* pass, const SGPropertyNode* props,
const SGReaderWriterOptions* options)
{
TexTuple attrs = makeTexTuple(effect, props, options, _type);
typename TexMap::iterator itr = texMap.find(attrs);
- if (itr != texMap.end())
- return itr->second.get();
- T* tex = new T;
- setAttrs(attrs, tex, options);
- texMap.insert(make_pair(attrs, tex));
- return tex;
+
+ ref_ptr<T> tex;
+ if ((itr != texMap.end())&&
+ (itr->second.lock(tex)))
+ {
+ return tex.release();
+ }
+
+ tex = new T;
+ if (!setAttrs(attrs, tex, options))
+ return NULL;
+
+ if (itr == texMap.end())
+ texMap.insert(make_pair(attrs, tex));
+ else
+ itr->second = tex; // update existing, but empty observer
+ return tex.release();
}
class WhiteTextureBuilder : public TextureBuilder
{
public:
- Texture* build(Effect* effect, const SGPropertyNode*,
+ Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
};
-Texture* WhiteTextureBuilder::build(Effect* effect, const SGPropertyNode*,
+Texture* WhiteTextureBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options)
{
return StateAttributeFactory::instance()->getWhiteTexture();
class TransparentTextureBuilder : public TextureBuilder
{
public:
- Texture* build(Effect* effect, const SGPropertyNode*,
+ Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
};
-Texture* TransparentTextureBuilder::build(Effect* effect, const SGPropertyNode*,
+Texture* TransparentTextureBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options)
{
return StateAttributeFactory::instance()->getTransparentTexture();
new TransparentTextureBuilder);
}
-osg::Image* make3DNoiseImage(int texSize)
-{
- osg::Image* image = new osg::Image;
- image->setImage(texSize, texSize, texSize,
- 4, GL_RGBA, GL_UNSIGNED_BYTE,
- new unsigned char[4 * texSize * texSize * texSize],
- osg::Image::USE_NEW_DELETE);
-
- const int startFrequency = 4;
- const int numOctaves = 4;
-
- int f, i, j, k, inc;
- double ni[3];
- double inci, incj, inck;
- int frequency = startFrequency;
- GLubyte *ptr;
- double amp = 0.5;
-
- SG_LOG(SG_INPUT, SG_INFO, "creating 3D noise texture... ");
-
- for (f = 0, inc = 0; f < numOctaves; ++f, frequency *= 2, ++inc, amp *= 0.5)
- {
- SetNoiseFrequency(frequency);
- ptr = image->data();
- ni[0] = ni[1] = ni[2] = 0;
-
- inci = 1.0 / (texSize / frequency);
- for (i = 0; i < texSize; ++i, ni[0] += inci)
- {
- incj = 1.0 / (texSize / frequency);
- for (j = 0; j < texSize; ++j, ni[1] += incj)
- {
- inck = 1.0 / (texSize / frequency);
- for (k = 0; k < texSize; ++k, ni[2] += inck, ptr += 4)
- {
- *(ptr+inc) = (GLubyte) (((noise3(ni) + 1.0) * amp) * 128.0);
- }
- }
- }
- }
-
- SG_LOG(SG_INPUT, SG_INFO, "creating 3D noise textures complete!");
- return image;
-}
-
class NoiseBuilder : public TextureBuilder
{
public:
- Texture* build(Effect* effect, const SGPropertyNode*,
+ Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
protected:
typedef map<int, ref_ptr<Texture3D> > NoiseMap;
NoiseMap _noises;
};
-Texture* NoiseBuilder::build(Effect* effect, const SGPropertyNode* props,
+Texture* NoiseBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode* props,
const SGReaderWriterOptions* options)
{
int texSize = 64;
"size");
if (sizeProp)
texSize = sizeProp->getValue<int>();
- NoiseMap::iterator itr = _noises.find(texSize);
- if (itr != _noises.end())
- return itr->second.get();
- Texture3D* noiseTexture = new osg::Texture3D;
- noiseTexture->setFilter(osg::Texture3D::MIN_FILTER, osg::Texture3D::LINEAR);
- noiseTexture->setFilter(osg::Texture3D::MAG_FILTER, osg::Texture3D::LINEAR);
- noiseTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture3D::REPEAT);
- noiseTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture3D::REPEAT);
- noiseTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture3D::REPEAT);
- noiseTexture->setImage( make3DNoiseImage(texSize) );
- _noises.insert(make_pair(texSize, noiseTexture));
- return noiseTexture;
+
+ return StateAttributeFactory::instance()->getNoiseTexture(texSize);
}
namespace
class CubeMapBuilder : public TextureBuilder
{
public:
- Texture* build(Effect* effect, const SGPropertyNode*,
+ Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
protected:
typedef map<CubeMapTuple, ref_ptr<TextureCubeMap> > CubeMap;
}
-Texture* CubeMapBuilder::build(Effect* effect, const SGPropertyNode* props,
+Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode* props,
const SGReaderWriterOptions* options)
{
// First check that there is a <images> tag
return true;
}
+class GBufferBuilder : public TextureBuilder
+{
+public:
+ GBufferBuilder() {}
+ Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
+ const SGReaderWriterOptions* options);
+private:
+ string buffer;
+};
+
+class BufferNameChangeListener : public SGPropertyChangeListener, public InitializeWhenAdded,
+ public Effect::Updater {
+public:
+ BufferNameChangeListener(Pass* p, int u, const std::string& pn) : pass(p), unit(u)
+ {
+ propName = new std::string(pn);
+ }
+ ~BufferNameChangeListener()
+ {
+ delete propName;
+ propName = 0;
+ }
+ void valueChanged(SGPropertyNode* node)
+ {
+ const char* buffer = node->getStringValue();
+ pass->setBufferUnit(unit, buffer);
+ }
+ void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
+ {
+ SGPropertyNode* listenProp = makeNode(propRoot, *propName);
+ delete propName;
+ propName = 0;
+ if (listenProp)
+ listenProp->addChangeListener(this, true);
+ }
+
+private:
+ ref_ptr<Pass> pass;
+ int unit;
+ std::string* propName;
+};
+
+Texture* GBufferBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+ const SGReaderWriterOptions* options)
+{
+ int unit = 0;
+ const SGPropertyNode* pUnit = prop->getChild("unit");
+ if (pUnit) {
+ unit = pUnit->getValue<int>();
+ } else {
+ SG_LOG(SG_INPUT, SG_ALERT, "no texture unit");
+ }
+ const SGPropertyNode* nameProp = getEffectPropertyChild(effect, prop,
+ "name");
+ if (!nameProp)
+ return 0;
+
+ if (nameProp->nChildren() == 0) {
+ buffer = nameProp->getStringValue();
+ pass->setBufferUnit( unit, buffer );
+ } else {
+ std::string propName = getGlobalProperty(nameProp, options);
+ BufferNameChangeListener* listener = new BufferNameChangeListener(pass, unit, propName);
+ effect->addUpdater(listener);
+ }
+
+ // Return white for now. Would be overridden in Technique::ProcessDrawable
+ return StateAttributeFactory::instance()->getWhiteTexture();
+}
+
+namespace
+{
+ TextureBuilder::Registrar installBuffer("buffer", new GBufferBuilder);
+}
+
}