]> git.mxchange.org Git - simgear.git/commitdiff
New effects from Till Busch: crops, water, landmass
authortimoore <timoore>
Sat, 8 Aug 2009 10:19:56 +0000 (10:19 +0000)
committerTim Moore <timoore@redhat.com>
Sun, 9 Aug 2009 21:56:10 +0000 (23:56 +0200)
As shown at LinuxTag, with modifications from Tim Moore: the base
landmass texture is mixed with the steepness and snow effects. Till's
new syntax for textures in effect files was also added. syntax for
textures. Also, syntax for accessing internal textures, such as Till's
3D noise texture, was added.

Several bugs in the effect inheritance algorithm were fixed.

12 files changed:
projects/VC7.1/SimGear.vcproj
simgear/scene/material/Effect.cxx
simgear/scene/material/EffectBuilder.cxx [new file with mode: 0644]
simgear/scene/material/EffectBuilder.hxx [new file with mode: 0644]
simgear/scene/material/Makefile.am
simgear/scene/material/Noise.cxx [new file with mode: 0644]
simgear/scene/material/Noise.hxx [new file with mode: 0644]
simgear/scene/material/TextureBuilder.cxx [new file with mode: 0644]
simgear/scene/material/TextureBuilder.hxx [new file with mode: 0644]
simgear/scene/material/makeEffect.cxx
simgear/scene/material/mat.cxx
simgear/scene/material/mat.hxx

index 1c1bb2c867637e63ceb3da3871916cc6fdfb52ef..36dc8e09b5cb45147d1e6fbeb4f15e058559520a 100755 (executable)
                        <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>
index a50dfd7811a24577f60c56eb098c0dd59a01328c..496d64f4f599477b87fc426a361b0dc5a5257bd6 100644 (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>
@@ -142,56 +147,6 @@ struct InstallAttributeBuilder
         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)
@@ -235,35 +190,6 @@ osg::Vec4f getColor(const SGPropertyNode* prop)
     }
 }
 
-// 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,
@@ -467,25 +393,6 @@ struct AlphaTestBuilder : public PassAttributeBuilder
 
 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},
@@ -514,13 +421,6 @@ TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop)
     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
 {
@@ -532,68 +432,7 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
                                         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");
@@ -609,6 +448,21 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
                        << 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) {
@@ -618,6 +472,8 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
     }
 }
 
+
+
 InstallAttributeBuilder<TextureUnitBuilder> textureUnitBuilder("texture-unit");
 
 typedef map<string, ref_ptr<Program> > ProgramMap;
@@ -626,6 +482,18 @@ ProgramMap 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,
@@ -662,6 +530,7 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
         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;
@@ -678,8 +547,8 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
                     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));
                         }
                     }
                 }
diff --git a/simgear/scene/material/EffectBuilder.cxx b/simgear/scene/material/EffectBuilder.cxx
new file mode 100644 (file)
index 0000000..b1f0920
--- /dev/null
@@ -0,0 +1,54 @@
+#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()
+{
+}
+}
diff --git a/simgear/scene/material/EffectBuilder.hxx b/simgear/scene/material/EffectBuilder.hxx
new file mode 100644 (file)
index 0000000..831c9fa
--- /dev/null
@@ -0,0 +1,157 @@
+// 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
index aee10b42ebdfabf3df8b42198b3d83f3782fb4cc..031e42148991e64348bacf46a1e13eb6757edee7 100644 (file)
@@ -6,25 +6,30 @@ noinst_HEADERS =
 
 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)
diff --git a/simgear/scene/material/Noise.cxx b/simgear/scene/material/Noise.cxx
new file mode 100644 (file)
index 0000000..23ecd79
--- /dev/null
@@ -0,0 +1,287 @@
+/* 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);
+}
diff --git a/simgear/scene/material/Noise.hxx b/simgear/scene/material/Noise.hxx
new file mode 100644 (file)
index 0000000..33716c9
--- /dev/null
@@ -0,0 +1,51 @@
+/* -*-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__
diff --git a/simgear/scene/material/TextureBuilder.cxx b/simgear/scene/material/TextureBuilder.cxx
new file mode 100644 (file)
index 0000000..2ea23c6
--- /dev/null
@@ -0,0 +1,277 @@
+// 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);
+}
+
+}
diff --git a/simgear/scene/material/TextureBuilder.hxx b/simgear/scene/material/TextureBuilder.hxx
new file mode 100644 (file)
index 0000000..259ef61
--- /dev/null
@@ -0,0 +1,34 @@
+// 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
index 913fcfbd6072f101a5ab7a420980a1f6da0555d6..0cdad0d957f7d349785457b15c03991cb697af79 100644 (file)
@@ -55,10 +55,7 @@ OpenThreads::ReentrantMutex effectMutex;
  * 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
@@ -69,15 +66,7 @@ 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;
 };
@@ -93,8 +82,6 @@ void mergePropertyTrees(SGPropertyNode* resultNode,
     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);
@@ -102,8 +89,7 @@ void mergePropertyTrees(SGPropertyNode* resultNode,
             = 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);
@@ -111,13 +97,13 @@ void mergePropertyTrees(SGPropertyNode* resultNode,
             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);
     }
 }
@@ -134,8 +120,10 @@ Effect* makeEffect(const string& name,
     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);
@@ -179,9 +167,15 @@ Effect* makeEffect(SGPropertyNode* prop,
     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;
     }
index 5cb949a93f2ed665e2c5c01ba8fef28291c389b8..dc79d094912d6dd3f146c37725875e2271acbba3 100644 (file)
@@ -269,13 +269,12 @@ void SGMaterial::buildEffectProperties(const osgDB::ReaderWriter::Options*
         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());
index 5b74412cfb7f95c20ddb995f4c1b8f3f90cd9d6d..c510575ed962f887cfeff099085f1c7a413bd4ee 100644 (file)
@@ -55,6 +55,7 @@ class StateSet;
 namespace simgear
 {
 class Effect;
+void reload_shaders();
 }
 
 class SGMaterialGlyph;