<File
RelativePath="..\..\simgear\scene\material\Effect.hxx">
</File>
+ <File
+ RelativePath="..\..\simgear\scene\material\EffectBuilder.cxx">
+ </File>
+ <File
+ RelativePath="..\..\simgear\scene\material\EffectBuilder.hxx">
+ </File>
<File
RelativePath="..\..\simgear\scene\material\EffectCullVisitor.cxx">
</File>
<File
RelativePath="..\..\simgear\scene\material\GLPredicate.hxx">
</File>
+ <File
+ RelativePath="..\..\simgear\scene\material\Noise.cxx">
+ </File>
+ <File
+ RelativePath="..\..\simgear\scene\material\Noise.hxx">
+ </File>
+
+ <File
+ RelativePath="..\..\simgear\scene\material\TextureBuilder.cxx">
+ </File>
+ <File
+ RelativePath="..\..\simgear\scene\material\TextureBuilder.hxx">
+ </File>
+
<File
RelativePath="..\..\simgear\scene\material\makeEffect.cxx">
</File>
#endif
#include "Effect.hxx"
+#include "EffectBuilder.hxx"
#include "Technique.hxx"
#include "Pass.hxx"
+#include "TextureBuilder.hxx"
#include <algorithm>
#include <functional>
#include <osg/ShadeModel>
#include <osg/StateSet>
#include <osg/TexEnv>
+#include <osg/Texture1D>
#include <osg/Texture2D>
+#include <osg/Texture3D>
+#include <osg/TextureRectangle>
#include <osg/Uniform>
#include <osg/Vec4d>
#include <osgUtil/CullVisitor>
passAttrMap.insert(make_pair(name, new T));
}
};
-// Simple tables of strings and OSG constants. The table intialization
-// *must* be in alphabetical order.
-template <typename T>
-struct EffectNameValue
-{
- // Don't use std::pair because we want to use aggregate intialization.
-
- const char* first;
- T second;
- class Compare
- {
- private:
- static bool compare(const char* lhs, const char* rhs)
- {
- return strcmp(lhs, rhs) < 0;
- }
- public:
- bool operator()(const EffectNameValue& lhs,
- const EffectNameValue& rhs) const
- {
- return compare(lhs.first, rhs.first);
- }
- bool operator()(const char* lhs, const EffectNameValue& rhs) const
- {
- return compare(lhs, rhs.first);
- }
- bool operator()(const EffectNameValue& lhs, const char* rhs) const
- {
- return compare (lhs.first, rhs);
- }
- };
-};
-
-template<typename ENV, typename T, int N>
-bool findAttr(const ENV (&attrs)[N], const SGPropertyNode* prop, T& result)
-{
- if (!prop)
- return false;
- const char* name = prop->getStringValue();
- if (!name)
- return false;
- std::pair<const ENV*, const ENV*> itrs
- = std::equal_range(&attrs[0], &attrs[N], name, typename ENV::Compare());
- if (itrs.first == itrs.second) {
- return false;
- } else {
- result = itrs.first->second;
- return true;
- }
-}
void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
}
}
-// Given a property node from a pass, get its value either from it or
-// from the effect parameters.
-const SGPropertyNode* getEffectPropertyNode(Effect* effect,
- const SGPropertyNode* prop)
-{
- if (!prop)
- return 0;
- if (prop->nChildren() > 0) {
- const SGPropertyNode* useProp = prop->getChild("use");
- if (!useProp || !effect->parametersProp)
- return prop;
- return effect->parametersProp->getNode(useProp->getStringValue());
- }
- return prop;
-}
-
-// Get a named child property from pass parameters or effect
-// parameters.
-const SGPropertyNode* getEffectPropertyChild(Effect* effect,
- const SGPropertyNode* prop,
- const char* name)
-{
- const SGPropertyNode* child = prop->getChild(name);
- if (!child)
- return 0;
- else
- return getEffectPropertyNode(effect, child);
-}
-
struct LightingBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
InstallAttributeBuilder<AlphaTestBuilder> installAlphaTest("alpha-test");
-EffectNameValue<Texture::FilterMode> filterModes[] =
-{
- { "linear", Texture::LINEAR },
- { "linear-mipmap-linear", Texture::LINEAR_MIPMAP_LINEAR},
- { "linear-mipmap-nearest", Texture::LINEAR_MIPMAP_NEAREST},
- { "nearest", Texture::NEAREST},
- { "nearest-mipmap-linear", Texture::NEAREST_MIPMAP_LINEAR},
- { "nearest-mipmap-nearest", Texture::NEAREST_MIPMAP_NEAREST}
-};
-
-EffectNameValue<Texture::WrapMode> wrapModes[] =
-{
- {"clamp", Texture::CLAMP},
- {"clamp-to-border", Texture::CLAMP_TO_BORDER},
- {"clamp-to-edge", Texture::CLAMP_TO_EDGE},
- {"mirror", Texture::MIRROR},
- {"repeat", Texture::REPEAT}
-};
-
EffectNameValue<TexEnv::Mode> texEnvModes[] =
{
{"add", TexEnv::ADD},
return env;
}
-typedef boost::tuple<string, Texture::FilterMode, Texture::FilterMode,
- Texture::WrapMode, Texture::WrapMode,
- Texture::WrapMode> TexTuple;
-
-typedef map<TexTuple, ref_ptr<Texture2D> > TexMap;
-
-TexMap texMap;
struct TextureUnitBuilder : PassAttributeBuilder
{
const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
- // First, all the texture properties
- const SGPropertyNode* pTexture2d = prop->getChild("texture2d");
- if (!pTexture2d)
- return;
- const SGPropertyNode* pImage
- = getEffectPropertyChild(effect, pTexture2d, "image");
- if (!pImage)
- return;
- const char* imageName = pImage->getStringValue();
- Texture::FilterMode minFilter = Texture::LINEAR_MIPMAP_LINEAR;
- findAttr(filterModes, getEffectPropertyChild(effect, pTexture2d, "filter"),
- minFilter);
- Texture::FilterMode magFilter = Texture::LINEAR;
- findAttr(filterModes, getEffectPropertyChild(effect, pTexture2d,
- "mag-filter"),
- magFilter);
- const SGPropertyNode* pWrapS
- = getEffectPropertyChild(effect, pTexture2d, "wrap-s");
- Texture::WrapMode sWrap = Texture::CLAMP;
- findAttr(wrapModes, pWrapS, sWrap);
- const SGPropertyNode* pWrapT
- = getEffectPropertyChild(effect, pTexture2d, "wrap-t");
- Texture::WrapMode tWrap = Texture::CLAMP;
- findAttr(wrapModes, pWrapT, tWrap);
- const SGPropertyNode* pWrapR
- = getEffectPropertyChild(effect, pTexture2d, "wrap-r");
- Texture::WrapMode rWrap = Texture::CLAMP;
- findAttr(wrapModes, pWrapR, rWrap);
- TexTuple tuple(imageName, minFilter, magFilter, sWrap, tWrap, rWrap);
- TexMap::iterator texIter = texMap.find(tuple);
- Texture2D* texture = 0;
- if (texIter != texMap.end()) {
- texture = texIter->second.get();
- } else {
- texture = new Texture2D;
- osgDB::ReaderWriter::ReadResult result
- = osgDB::Registry::instance()->readImage(imageName, options);
- if (result.success()) {
- osg::Image* image = result.getImage();
- texture->setImage(image);
- int s = image->s();
- int t = image->t();
-
- if (s <= t && 32 <= s) {
- SGSceneFeatures::instance()->setTextureCompression(texture);
- } else if (t < s && 32 <= t) {
- SGSceneFeatures::instance()->setTextureCompression(texture);
- }
- texture->setMaxAnisotropy(SGSceneFeatures::instance()
- ->getTextureFilter());
- } else {
- SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file "
- << imageName);
- }
- // texture->setDataVariance(osg::Object::STATIC);
- texture->setFilter(Texture::MIN_FILTER, minFilter);
- texture->setFilter(Texture::MAG_FILTER, magFilter);
- texture->setWrap(Texture::WRAP_S, sWrap);
- texture->setWrap(Texture::WRAP_T, tWrap);
- texture->setWrap(Texture::WRAP_R, rWrap);
- texMap.insert(make_pair(tuple, texture));
- }
+
// Decode the texture unit
int unit = 0;
const SGPropertyNode* pUnit = prop->getChild("unit");
<< lex.what());
}
}
+ const SGPropertyNode* pType = prop->getChild("type");
+ string type;
+ if (!pType)
+ type = "2d";
+ else
+ type = pType->getStringValue();
+ Texture* texture = 0;
+ try {
+ texture = TextureBuilder::buildFromType(effect, type, prop,
+ options);
+ }
+ catch (BuilderException& e) {
+ SG_LOG(SG_INPUT, SG_ALERT, "No image file for texture, using white ");
+ texture = StateAttributeFactory::instance()->getWhiteTexture();
+ }
pass->setTextureAttributeAndModes(unit, texture);
const SGPropertyNode* envProp = prop->getChild("environment");
if (envProp) {
}
}
+
+
InstallAttributeBuilder<TextureUnitBuilder> textureUnitBuilder("texture-unit");
typedef map<string, ref_ptr<Program> > ProgramMap;
typedef map<string, ref_ptr<Shader> > ShaderMap;
ShaderMap shaderMap;
+void reload_shaders()
+{
+ for(ShaderMap::iterator sitr = shaderMap.begin(); sitr != shaderMap.end(); ++sitr)
+ {
+ Shader *shader = sitr->second.get();
+ string fileName = osgDB::findDataFile(sitr->first);
+ if (!fileName.empty()) {
+ shader->loadShaderSourceFromFile(fileName);
+ }
+ }
+}
+
struct ShaderProgramBuilder : PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
program = pitr->second.get();
} else {
program = new Program;
+ program->setName(programKey);
// Add vertex shaders, then fragment shaders
PropertyList& pvec = pVertShaders;
Shader::Type stype = Shader::VERTEX;
if (!fileName.empty()) {
ref_ptr<Shader> shader = new Shader(stype);
if (shader->loadShaderSourceFromFile(fileName)) {
- shaderMap.insert(make_pair(shaderName, shader));
program->addShader(shader.get());
+ shaderMap.insert(make_pair(shaderName, shader));
}
}
}
--- /dev/null
+#include "EffectBuilder.hxx"
+#include "Effect.hxx"
+
+namespace simgear
+{
+
+// Given a property node from a pass, get its value either from it or
+// from the effect parameters.
+const SGPropertyNode* getEffectPropertyNode(Effect* effect,
+ const SGPropertyNode* prop)
+{
+ if (!prop)
+ return 0;
+ if (prop->nChildren() > 0) {
+ const SGPropertyNode* useProp = prop->getChild("use");
+ if (!useProp || !effect->parametersProp)
+ return prop;
+ return effect->parametersProp->getNode(useProp->getStringValue());
+ }
+ return prop;
+}
+
+// Get a named child property from pass parameters or effect
+// parameters.
+const SGPropertyNode* getEffectPropertyChild(Effect* effect,
+ const SGPropertyNode* prop,
+ const char* name)
+{
+ const SGPropertyNode* child = prop->getChild(name);
+ if (!child)
+ return 0;
+ else
+ return getEffectPropertyNode(effect, child);
+}
+
+BuilderException::BuilderException()
+{
+}
+
+BuilderException::BuilderException(const char* message, const char* origin)
+ : sg_exception(message, origin)
+{
+}
+
+BuilderException::BuilderException(const std::string& message,
+ const std::string& origin)
+ : sg_exception(message, origin)
+{
+}
+
+BuilderException::~BuilderException() throw()
+{
+}
+}
--- /dev/null
+// Copyright (C) 2009 Tim Moore timoore@redhat.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifndef SIMGEAR_EFFECTBUILDER_HXX
+#define SIMGEAR_EFFECTBUILDER_HXX 1
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <cstring>
+
+#include <osgDB/Registry>
+
+#include <simgear/props/props.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include <simgear/structure/Singleton.hxx>
+
+/**
+ * Support classes for parsing effects.
+ */
+
+namespace simgear
+{
+class Effect;
+
+/**
+ * Builder that returns an object, probably an OSG object.
+ */
+template<typename T>
+class EffectBuilder : public SGReferenced
+{
+public:
+ virtual ~EffectBuilder() {}
+ virtual T* build(Effect* effect, const SGPropertyNode*,
+ const osgDB::ReaderWriter::Options* options) = 0;
+ static T* buildFromType(Effect* effect, const std::string& type,
+ const SGPropertyNode*props,
+ const osgDB::ReaderWriter::Options* options)
+ {
+ BuilderMap& builderMap = getMap();
+ typename BuilderMap::iterator iter = builderMap.find(type);
+ if (iter != builderMap.end())
+ return iter->second->build(effect, props, options);
+ else
+ return 0;
+ }
+ struct Registrar;
+ friend struct Registrar;
+ struct Registrar
+ {
+ Registrar(const std::string& type, EffectBuilder* builder)
+ {
+ getMap().insert(std::make_pair(type, builder));
+ }
+ };
+protected:
+ typedef std::map<std::string, SGSharedPtr<EffectBuilder> > BuilderMap;
+ struct BuilderMapSingleton : public simgear::Singleton<BuilderMapSingleton>
+ {
+ BuilderMap _map;
+ };
+ static BuilderMap& getMap()
+ {
+ return BuilderMapSingleton::instance()->_map;
+ }
+};
+
+// Simple tables of strings and constants. The table intialization
+// *must* be in alphabetical order.
+template <typename T>
+struct EffectNameValue
+{
+ // Don't use std::pair because we want to use aggregate intialization.
+
+ const char* first;
+ T second;
+ class Compare
+ {
+ private:
+ static bool compare(const char* lhs, const char* rhs)
+ {
+ return std::strcmp(lhs, rhs) < 0;
+ }
+ public:
+ bool operator()(const EffectNameValue& lhs,
+ const EffectNameValue& rhs) const
+ {
+ return compare(lhs.first, rhs.first);
+ }
+ bool operator()(const char* lhs, const EffectNameValue& rhs) const
+ {
+ return compare(lhs, rhs.first);
+ }
+ bool operator()(const EffectNameValue& lhs, const char* rhs) const
+ {
+ return compare (lhs.first, rhs);
+ }
+ };
+};
+
+template<typename ENV, typename T, int N>
+bool findAttr(const ENV (&attrs)[N], const SGPropertyNode* prop, T& result)
+{
+ if (!prop)
+ return false;
+ const char* name = prop->getStringValue();
+ if (!name)
+ return false;
+ std::pair<const ENV*, const ENV*> itrs
+ = std::equal_range(&attrs[0], &attrs[N], name, typename ENV::Compare());
+ if (itrs.first == itrs.second) {
+ return false;
+ } else {
+ result = itrs.first->second;
+ return true;
+ }
+}
+
+/**
+ * Given a property node from a pass, get its value either from it or
+ * from the effect parameters.
+ */
+
+const SGPropertyNode* getEffectPropertyNode(Effect* effect,
+ const SGPropertyNode* prop);
+/**
+ * Get a named child property from pass parameters or effect
+ * parameters.
+ */
+const SGPropertyNode* getEffectPropertyChild(Effect* effect,
+ const SGPropertyNode* prop,
+ const char* name);
+
+class BuilderException : public sg_exception
+{
+public:
+ BuilderException();
+ BuilderException(const char* message, const char* origin = 0);
+ BuilderException(const std::string& message, const std::string& = "");
+ virtual ~BuilderException() throw();
+};
+}
+#endif
include_HEADERS = \
Effect.hxx \
+ EffectBuilder.hxx \
EffectCullVisitor.hxx \
EffectGeode.hxx \
GLPredicate.hxx \
Pass.hxx \
Technique.hxx \
+ TextureBuilder.hxx \
mat.hxx \
matlib.hxx \
matmodel.hxx
libsgmaterial_a_SOURCES = \
Effect.cxx \
+ EffectBuilder.cxx \
EffectCullVisitor.cxx \
EffectGeode.cxx \
GLPredicate.cxx \
Pass.cxx \
Technique.cxx \
+ TextureBuilder.cxx \
makeEffect.cxx \
mat.cxx \
matlib.cxx \
- matmodel.cxx
+ matmodel.cxx \
+ Noise.cxx
INCLUDES = -I$(top_srcdir)
--- /dev/null
+/* OpenSceneGraph example, osgshaders.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+/************************************************************************
+ * *
+ * Copyright (C) 2002 3Dlabs Inc. Ltd. *
+ * *
+ ************************************************************************/
+
+#include <math.h>
+#include <stdlib.h>
+
+/* Coherent noise function over 1, 2 or 3 dimensions */
+/* (copyright Ken Perlin) */
+
+#define MAXB 0x100
+#define N 0x1000
+#define NP 12 /* 2^N */
+#define NM 0xfff
+
+#define s_curve(t) ( t * t * (3. - 2. * t) )
+#define lerp(t, a, b) ( a + t * (b - a) )
+#define setup(i,b0,b1,r0,r1)\
+ t = vec[i] + N;\
+ b0 = ((int)t) & BM;\
+ b1 = (b0+1) & BM;\
+ r0 = t - (int)t;\
+ r1 = r0 - 1.;
+#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
+#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+
+static void initNoise(void);
+
+static int p[MAXB + MAXB + 2];
+static double g3[MAXB + MAXB + 2][3];
+static double g2[MAXB + MAXB + 2][2];
+static double g1[MAXB + MAXB + 2];
+
+int start;
+int B;
+int BM;
+
+
+void SetNoiseFrequency(int frequency)
+{
+ start = 1;
+ B = frequency;
+ BM = B-1;
+}
+
+double noise1(double arg)
+{
+ int bx0, bx1;
+ double rx0, rx1, sx, t, u, v, vec[1];
+
+ vec[0] = arg;
+ if (start) {
+ start = 0;
+ initNoise();
+ }
+
+ setup(0,bx0,bx1,rx0,rx1);
+
+ sx = s_curve(rx0);
+ u = rx0 * g1[ p[ bx0 ] ];
+ v = rx1 * g1[ p[ bx1 ] ];
+
+ return(lerp(sx, u, v));
+}
+
+double noise2(double vec[2])
+{
+ int bx0, bx1, by0, by1, b00, b10, b01, b11;
+ double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+ int i, j;
+
+ if (start) {
+ start = 0;
+ initNoise();
+ }
+
+ setup(0, bx0,bx1, rx0,rx1);
+ setup(1, by0,by1, ry0,ry1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+ sx = s_curve(rx0);
+ sy = s_curve(ry0);
+
+ q = g2[ b00 ] ; u = at2(rx0,ry0);
+ q = g2[ b10 ] ; v = at2(rx1,ry0);
+ a = lerp(sx, u, v);
+
+ q = g2[ b01 ] ; u = at2(rx0,ry1);
+ q = g2[ b11 ] ; v = at2(rx1,ry1);
+ b = lerp(sx, u, v);
+
+ return lerp(sy, a, b);
+}
+
+double noise3(double vec[3])
+{
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+ int i, j;
+
+ if (start) {
+ start = 0;
+ initNoise();
+ }
+
+ setup(0, bx0,bx1, rx0,rx1);
+ setup(1, by0,by1, ry0,ry1);
+ setup(2, bz0,bz1, rz0,rz1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+ t = s_curve(rx0);
+ sy = s_curve(ry0);
+ sz = s_curve(rz0);
+
+ q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
+ q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
+ q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
+ b = lerp(t, u, v);
+
+ c = lerp(sy, a, b);
+
+ q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
+ q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
+ q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
+ b = lerp(t, u, v);
+
+ d = lerp(sy, a, b);
+
+ //fprintf(stderr, "%f\n", lerp(sz, c, d));
+
+ return lerp(sz, c, d);
+}
+
+void normalize2(double v[2])
+{
+ double s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+}
+
+void normalize3(double v[3])
+{
+ double s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+ v[2] = v[2] / s;
+}
+
+void initNoise(void)
+{
+ int i, j, k;
+
+ srand(30757);
+ for (i = 0 ; i < B ; i++) {
+ p[i] = i;
+ g1[i] = (double)((rand() % (B + B)) - B) / B;
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[i][j] = (double)((rand() % (B + B)) - B) / B;
+ normalize2(g2[i]);
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[i][j] = (double)((rand() % (B + B)) - B) / B;
+ normalize3(g3[i]);
+ }
+
+ while (--i) {
+ k = p[i];
+ p[i] = p[j = rand() % B];
+ p[j] = k;
+ }
+
+ for (i = 0 ; i < B + 2 ; i++) {
+ p[B + i] = p[i];
+ g1[B + i] = g1[i];
+ for (j = 0 ; j < 2 ; j++)
+ g2[B + i][j] = g2[i][j];
+ for (j = 0 ; j < 3 ; j++)
+ g3[B + i][j] = g3[i][j];
+ }
+}
+
+/* --- My harmonic summing functions - PDB --------------------------*/
+
+/*
+ In what follows "alpha" is the weight when the sum is formed.
+ Typically it is 2, As this approaches 1 the function is noisier.
+ "beta" is the harmonic scaling/spacing, typically 2.
+*/
+
+double PerlinNoise1D(double x,double alpha,double beta,int n)
+{
+ int i;
+ double val,sum = 0;
+ double p,scale = 1;
+
+ p = x;
+ for (i=0;i<n;i++) {
+ val = noise1(p);
+ sum += val / scale;
+ scale *= alpha;
+ p *= beta;
+ }
+ return(sum);
+}
+
+double PerlinNoise2D(double x,double y,double alpha,double beta,int n)
+{
+ int i;
+ double val,sum = 0;
+ double p[2],scale = 1;
+
+ p[0] = x;
+ p[1] = y;
+ for (i=0;i<n;i++) {
+ val = noise2(p);
+ sum += val / scale;
+ scale *= alpha;
+ p[0] *= beta;
+ p[1] *= beta;
+ }
+ return(sum);
+}
+
+double PerlinNoise3D(double x,double y,double z,double alpha,double beta,int n)
+{
+ int i;
+ double val,sum = 0;
+ double p[3],scale = 1;
+
+ p[0] = x;
+ p[1] = y;
+ p[2] = z;
+ for (i=0;i<n;i++) {
+ val = noise3(p);
+ sum += val / scale;
+ scale *= alpha;
+ p[0] *= beta;
+ p[1] *= beta;
+ p[2] *= beta;
+ }
+ return(sum);
+}
--- /dev/null
+/* -*-c++-*-
+*
+* OpenSceneGraph example, osgshaders.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+
+/************************************************************************
+ * *
+ * Copyright (C) 2002 3Dlabs Inc. Ltd. *
+ * *
+ ***********************************************************************/
+
+#ifndef __ogl2_demo_h__
+#define __ogl2_demo_h__
+
+
+extern void SetNoiseFrequency(int frequency);
+
+extern double noise1(double arg);
+extern double noise2(double vec[2]);
+extern double noise3(double vec[3]);
+extern void normalize2(double vec[2]);
+extern void normalize3(double vec[3]);
+
+/*
+ In what follows "alpha" is the weight when the sum is formed.
+ Typically it is 2, As this approaches 1 the function is noisier.
+ "beta" is the harmonic scaling/spacing, typically 2.
+*/
+
+extern double PerlinNoise1D(double x,double alpha, double beta, int n);
+extern double PerlinNoise2D(double x,double y,double alpha, double beta, int n);
+extern double PerlinNoise3D(double x,double y,double z,double alpha, double beta, int n);
+
+
+#endif // __ogl2_demo_h__
--- /dev/null
+// Copyright (C) 2009 Tim Moore timoore@redhat.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#include "TextureBuilder.hxx"
+
+#include <osg/Texture1D>
+#include <osg/Texture2D>
+#include <osg/Texture3D>
+#include <osg/TextureRectangle>
+#include <osgDB/FileUtils>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+
+#include <simgear/scene/util/SGSceneFeatures.hxx>
+#include <simgear/scene/util/StateAttributeFactory.hxx>
+
+#include "Noise.hxx"
+
+namespace simgear
+{
+using namespace std;
+using namespace osg;
+
+// Hack to force inclusion of TextureBuilder.cxx in library
+osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
+ const SGPropertyNode*props,
+ const osgDB::ReaderWriter::Options*
+ options)
+{
+ return EffectBuilder<Texture>::buildFromType(effect, type, props, options);
+}
+
+typedef boost::tuple<string, Texture::FilterMode, Texture::FilterMode,
+ Texture::WrapMode, Texture::WrapMode, Texture::WrapMode,
+ string> TexTuple;
+
+namespace
+{
+EffectNameValue<Texture::FilterMode> filterModes[] =
+{
+ { "linear", Texture::LINEAR },
+ { "linear-mipmap-linear", Texture::LINEAR_MIPMAP_LINEAR},
+ { "linear-mipmap-nearest", Texture::LINEAR_MIPMAP_NEAREST},
+ { "nearest", Texture::NEAREST},
+ { "nearest-mipmap-linear", Texture::NEAREST_MIPMAP_LINEAR},
+ { "nearest-mipmap-nearest", Texture::NEAREST_MIPMAP_NEAREST}
+};
+
+EffectNameValue<Texture::WrapMode> wrapModes[] =
+{
+ {"clamp", Texture::CLAMP},
+ {"clamp-to-border", Texture::CLAMP_TO_BORDER},
+ {"clamp-to-edge", Texture::CLAMP_TO_EDGE},
+ {"mirror", Texture::MIRROR},
+ {"repeat", Texture::REPEAT}
+};
+
+
+
+TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
+ const osgDB::ReaderWriter::Options* options,
+ const string& texType)
+{
+ Texture::FilterMode minFilter = Texture::LINEAR_MIPMAP_LINEAR;
+ findAttr(filterModes, getEffectPropertyChild(effect, props, "filter"),
+ minFilter);
+ Texture::FilterMode magFilter = Texture::LINEAR;
+ findAttr(filterModes, getEffectPropertyChild(effect, props,
+ "mag-filter"),
+ magFilter);
+ const SGPropertyNode* pWrapS
+ = getEffectPropertyChild(effect, props, "wrap-s");
+ Texture::WrapMode sWrap = Texture::CLAMP;
+ findAttr(wrapModes, pWrapS, sWrap);
+ const SGPropertyNode* pWrapT
+ = getEffectPropertyChild(effect, props, "wrap-t");
+ Texture::WrapMode tWrap = Texture::CLAMP;
+ findAttr(wrapModes, pWrapT, tWrap);
+ const SGPropertyNode* pWrapR
+ = getEffectPropertyChild(effect, props, "wrap-r");
+ Texture::WrapMode rWrap = Texture::CLAMP;
+ findAttr(wrapModes, pWrapR, rWrap);
+ const SGPropertyNode* pImage
+ = getEffectPropertyChild(effect, props, "image");
+ string imageName;
+ if (pImage)
+ imageName = pImage->getStringValue();
+ string absFileName = osgDB::findDataFile(imageName, options);
+ return TexTuple(absFileName, minFilter, magFilter, sWrap, tWrap, rWrap,
+ texType);
+}
+
+void setAttrs(const TexTuple& attrs, Texture* tex,
+ const osgDB::ReaderWriter::Options* options)
+{
+ const string& imageName = attrs.get<0>();
+ if (imageName.empty()) {
+ throw BuilderException("no image file");
+ } else {
+ osgDB::ReaderWriter::ReadResult result
+ = osgDB::Registry::instance()->readImage(imageName, options);
+ if (result.success()) {
+ osg::Image* image = result.getImage();
+ tex->setImage(GL_FRONT_AND_BACK, image);
+ 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);
+ }
+ }
+ // 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>());
+}
+}
+
+template<typename T>
+class TexBuilder : public TextureBuilder
+{
+public:
+ TexBuilder(const string& texType) : _type(texType) {}
+ Texture* build(Effect* effect, const SGPropertyNode*,
+ const osgDB::ReaderWriter::Options* options);
+protected:
+ typedef map<TexTuple, ref_ptr<T> > TexMap;
+ TexMap texMap;
+ const string _type;
+};
+
+template<typename T>
+Texture* TexBuilder<T>::build(Effect* effect, const SGPropertyNode* props,
+ const osgDB::ReaderWriter::Options* 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;
+}
+
+
+namespace
+{
+TextureBuilder::Registrar install1D("1d", new TexBuilder<Texture1D>("1d"));
+TextureBuilder::Registrar install2D("2d", new TexBuilder<Texture2D>("2d"));
+TextureBuilder::Registrar install3D("3d", new TexBuilder<Texture3D>("3d"));
+}
+
+class WhiteTextureBuilder : public TextureBuilder
+{
+public:
+ Texture* build(Effect* effect, const SGPropertyNode*,
+ const osgDB::ReaderWriter::Options* options);
+};
+
+Texture* WhiteTextureBuilder::build(Effect* effect, const SGPropertyNode*,
+ const osgDB::ReaderWriter::Options* options)
+{
+ return StateAttributeFactory::instance()->getWhiteTexture();
+}
+
+namespace
+{
+TextureBuilder::Registrar installWhite("white", new WhiteTextureBuilder);
+}
+
+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;
+
+ osg::notify(osg::WARN) << "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);
+ }
+ }
+ }
+ }
+
+ osg::notify(osg::WARN) << "DONE" << std::endl;
+ return image;
+}
+
+class NoiseBuilder : public TextureBuilder
+{
+public:
+ Texture* build(Effect* effect, const SGPropertyNode*,
+ const osgDB::ReaderWriter::Options* options);
+protected:
+ typedef map<int, ref_ptr<Texture3D> > NoiseMap;
+ NoiseMap _noises;
+};
+
+Texture* NoiseBuilder::build(Effect* effect, const SGPropertyNode* props,
+ const osgDB::ReaderWriter::Options* options)
+{
+ int texSize = 64;
+ const SGPropertyNode* sizeProp = getEffectPropertyChild(effect, props,
+ "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;
+}
+
+namespace
+{
+TextureBuilder::Registrar installNoise("noise", new NoiseBuilder);
+}
+
+}
--- /dev/null
+// Copyright (C) 2009 Tim Moore timoore@redhat.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifndef SIMGEAR_TEXTUREBUILDER_HXX
+#define SIMGEAR_TEXTUREBUILDER_HXX 1
+
+#include <osg/Texture>
+#include "EffectBuilder.hxx"
+
+namespace simgear
+{
+class TextureBuilder : public EffectBuilder<osg::Texture>
+{
+public:
+ // Hack to force inclusion of TextureBuilder.cxx in library
+ static osg::Texture* buildFromType(Effect* effect, const std::string& type,
+ const SGPropertyNode*props,
+ const osgDB::ReaderWriter::Options* options);
+};
+}
+#endif
* of the result. Otherwise the left children are placed after the
* right children in the result.
*
- * Nodes are considered identical if:
- * Their names are equal;
- * Either they both have "name" children and their values are equal;
- * or their indexes are equal.
+ * Nodes are considered equal if their names and indexes are equal.
*/
struct PropPredicate
{
if (strcmp(node->getName(), arg->getName()))
return false;
- const SGPropertyNode* nodeName = node->getChild("name");
- const SGPropertyNode* argName = arg->getChild("name");
- if (nodeName && argName)
- return !strcmp(nodeName->getStringValue(),
- argName->getStringValue());
- else if (!(nodeName || argName))
- return node->getIndex() == arg->getIndex();
- else
- return false;
+ return node->getIndex() == arg->getIndex();
}
const SGPropertyNode* node;
};
RawPropVector leftChildren;
for (int i = 0; i < left->nChildren(); ++i)
leftChildren.push_back(left->getChild(i));
- // Maximum index of nodes (with same names) we've created.
- map<string, int> nodeIndex;
// Merge identical nodes
for (int i = 0; i < right->nChildren(); ++i) {
const SGPropertyNode* node = right->getChild(i);
= find_if(leftChildren.begin(), leftChildren.end(),
PropPredicate(node));
SGPropertyNode* newChild
- = resultNode->getChild(node->getName(),
- nodeIndex[node->getName()]++, true);
+ = resultNode->getChild(node->getName(), node->getIndex(), true);
if (litr != leftChildren.end()) {
mergePropertyTrees(newChild, *litr, node);
leftChildren.erase(litr);
copyProperties(node, newChild);
}
}
+ // Now copy nodes remaining in the left tree
for (RawPropVector::iterator itr = leftChildren.begin(),
e = leftChildren.end();
itr != e;
++itr) {
SGPropertyNode* newChild
- = resultNode->getChild((*itr)->getName(),
- nodeIndex[(*itr)->getName()]++, true);
+ = resultNode->getChild((*itr)->getName(), (*itr)->getIndex(), true);
copyProperties(*itr, newChild);
}
}
effectFileName += ".eff";
string absFileName
= osgDB::findDataFile(effectFileName, options);
- if (absFileName.empty())
+ if (absFileName.empty()) {
+ SG_LOG(SG_INPUT, SG_WARN, "can't find \"" << effectFileName << "\"");
return 0;
+ }
SGPropertyNode_ptr effectProps = new SGPropertyNode();
readProperties(absFileName, effectProps.ptr(), 0, true);
Effect* result = makeEffect(effectProps.ptr(), realizeTechniques, options);
if (inheritProp) {
parent = makeEffect(inheritProp->getStringValue(), realizeTechniques,
options);
- effect->root = new SGPropertyNode;
- mergePropertyTrees(effect->root, prop, parent->root);
- effect->root->removeChild("inherits-from");
+ if(parent)
+ {
+ effect->root = new SGPropertyNode;
+ mergePropertyTrees(effect->root, prop, parent->root);
+ effect->root->removeChild("inherits-from");
+ } else {
+ effect->root = prop;
+ effect->root->removeChild("inherits-from");
+ }
} else {
effect->root = prop;
}
copyProperties(propRoot, effectProp);
SGPropertyNode* effectParamProp = effectProp->getChild("parameters", 0);
SGPropertyNode* texProp = makeChild(effectParamProp, "texture");
- SGPropertyNode* tex2dProp = makeChild(texProp, "texture2d");
- makeChild(tex2dProp, "image")->setStringValue(matState.texture_path);
- makeChild(tex2dProp, "filter")
+ makeChild(texProp, "image")->setStringValue(matState.texture_path);
+ makeChild(texProp, "filter")
->setStringValue(mipmap ? "linear-mipmap-linear" : "nearest");
- makeChild(tex2dProp, "wrap-s")
+ makeChild(texProp, "wrap-s")
->setStringValue(wrapu ? "repeat" : "clamp");
- makeChild(tex2dProp, "wrap-t")
+ makeChild(texProp, "wrap-t")
->setStringValue(wrapv ? "repeat" : "clamp");
matState.effect = makeEffect(effectProp, false, options);
matState.effect->setUserData(user.get());
namespace simgear
{
class Effect;
+void reload_shaders();
}
class SGMaterialGlyph;