]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/material/mat.cxx
Work around apparent OSG 3.2.0 normal binding bug.
[simgear.git] / simgear / scene / material / mat.cxx
index 582571f3096d734e58558fb077520530c44f32b6..46af662b05166a22def634adb0e7a6821684dc20 100644 (file)
 #include <simgear/misc/sgstream.hxx>
 #include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/props/props_io.hxx>
+#include <simgear/props/vectorPropTemplates.hxx>
 #include <simgear/scene/model/model.hxx>
+#include <simgear/scene/material/matmodel.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
 #include <simgear/scene/util/StateAttributeFactory.hxx>
+#include <simgear/props/condition.hxx>
+#include <simgear/scene/util/SGSceneFeatures.hxx>
+#include <simgear/scene/tgdb/SGTexturedTriangleBin.hxx>
 
 #include "Effect.hxx"
 #include "Technique.hxx"
@@ -135,7 +140,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
         tpath.append(tname);
         string fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
         if (fullTexPath.empty()) {
-            tpath = SGPath("Textures");
+            tpath.set("Textures");
             tpath.append(tname);
             fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
             if (fullTexPath.empty()) {
@@ -172,7 +177,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
             tpath.append(tname);
             string fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
             if (fullTexPath.empty()) {
-                tpath = SGPath("Textures");
+                tpath.set("Textures");
                 tpath.append(tname);
                 fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
                 if (fullTexPath.empty() ) {
@@ -197,7 +202,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
         }
     }
 
-    if (textures.size() == 0 && texturesets.size() == 0) {
+    if (textures.empty() && texturesets.empty()) {
         SGPath tpath("Textures");
         tpath.append("Terrain");
         tpath.append("unknown.rgb");
@@ -216,7 +221,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
             string fullMaskPath = SGModelLib::findDataFile(ompath.str(), options);
 
             if (fullMaskPath.empty()) {
-                ompath = SGPath("Textures");
+                ompath.set("Textures");
                 ompath.append(omname);
                 fullMaskPath = SGModelLib::findDataFile(ompath.str(), options);
             }
@@ -234,11 +239,14 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
 
                     bool dds_mask = (ompath.lower_extension() == "dds");
 
-                    if (dds[i] != dds_mask) {
+                    if (i < dds.size() && dds[i] != dds_mask) {
                         // Texture format does not match mask format. This is relevant for
                         // the object mask, as DDS textures have an origin at the bottom
-                        // left rather than top left, therefore we flip the object mask
-                        // vertically.
+                        // left rather than top left. Therefore we flip a copy of the image
+                        // (otherwise a second reference to the object mask would flip it
+                        // back!).                
+                        SG_LOG(SG_GENERAL, SG_DEBUG, "Flipping object mask" << omname);  
+                        image = (osg::Image* ) image->clone(osg::CopyOp::SHALLOW_COPY);
                         image->flipVertical();
                     }
 
@@ -264,11 +272,68 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
     wrapv = props->getBoolValue("wrapv", true);
     mipmap = props->getBoolValue("mipmap", true);
     light_coverage = props->getDoubleValue("light-coverage", 0.0);
+    
+    // Building properties
+    building_coverage = props->getDoubleValue("building-coverage", 0.0);
+    building_spacing = props->getDoubleValue("building-spacing-m", 5.0);
+    
+    string bt = props->getStringValue("building-texture", "Textures/buildings.png");
+    building_texture = SGModelLib::findDataFile(bt, options);    
+    
+    if (building_texture.empty()) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" << bt);
+    }
+    
+    bt = props->getStringValue("building-lightmap", "Textures/buildings-lightmap.png");
+    building_lightmap = SGModelLib::findDataFile(bt, options);    
+    
+    if (building_lightmap.empty()) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" << bt);
+    }    
+            
+    building_small_ratio = props->getDoubleValue("building-small-ratio", 0.8);
+    building_medium_ratio = props->getDoubleValue("building-medium-ratio", 0.15);
+    building_large_ratio =  props->getDoubleValue("building-large-ratio", 0.05);
+    
+    building_small_pitch =  props->getDoubleValue("building-small-pitch", 0.8);
+    building_medium_pitch =  props->getDoubleValue("building-medium-pitch", 0.2);
+    building_large_pitch =  props->getDoubleValue("building-large-pitch", 0.1);
+
+    building_small_min_floors = props->getIntValue("building-small-min-floors", 1);
+    building_small_max_floors = props->getIntValue("building-small-max-floors", 3);
+    building_medium_min_floors = props->getIntValue("building-medium-min-floors", 3);
+    building_medium_max_floors = props->getIntValue("building-medium-max-floors", 8);
+    building_large_min_floors = props->getIntValue("building-large-min-floors", 5);
+    building_large_max_floors = props->getIntValue("building-large-max-floors", 20);
+    
+    building_small_min_width = props->getFloatValue("building-small-min-width-m", 15.0);
+    building_small_max_width = props->getFloatValue("building-small-max-width-m", 60.0);
+    building_small_min_depth = props->getFloatValue("building-small-min-depth-m", 10.0);
+    building_small_max_depth = props->getFloatValue("building-small-max-depth-m", 20.0);
+    
+    building_medium_min_width = props->getFloatValue("building-medium-min-width-m", 25.0);
+    building_medium_max_width = props->getFloatValue("building-medium-max-width-m", 50.0);
+    building_medium_min_depth = props->getFloatValue("building-medium-min-depth-m", 20.0);
+    building_medium_max_depth = props->getFloatValue("building-medium-max-depth-m", 50.0);
+    
+    building_large_min_width = props->getFloatValue("building-large-min-width-m", 50.0);
+    building_large_max_width = props->getFloatValue("building-large-max-width-m", 75.0);
+    building_large_min_depth = props->getFloatValue("building-large-min-depth-m", 50.0);
+    building_large_max_depth = props->getFloatValue("building-large-max-depth-m", 75.0);
+
+    building_range = props->getDoubleValue("building-range-m", 10000.0);
+    
+    cos_object_max_density_slope_angle  = cos(props->getFloatValue("object-max-density-angle-deg", 20.0) * osg::PI/180.0);
+    cos_object_zero_density_slope_angle = cos(props->getFloatValue("object-zero-density-angle-deg", 30.0) * osg::PI/180.0);
+        
+    // Random vegetation properties
     wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
     tree_height = props->getDoubleValue("tree-height-m", 0.0);
     tree_width = props->getDoubleValue("tree-width-m", 0.0);
     tree_range = props->getDoubleValue("tree-range-m", 0.0);
     tree_varieties = props->getIntValue("tree-varieties", 1);
+    cos_tree_max_density_slope_angle  = cos(props->getFloatValue("tree-max-density-angle-deg", 30.0) * osg::PI/180.0);
+    cos_tree_zero_density_slope_angle = cos(props->getFloatValue("tree-zero-density-angle-deg", 45.0) * osg::PI/180.0);
 
     const SGPropertyNode* treeTexNode = props->getChild("tree-texture");
     
@@ -281,7 +346,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
             tree_texture = SGModelLib::findDataFile(treePath.str(), options);
 
             if (tree_texture.empty()) {
-                treePath = SGPath("Textures");
+                treePath.set("Textures");
                 treePath.append(treeTexPath);
                 tree_texture = SGModelLib::findDataFile(treePath.str(), options);
             }
@@ -289,11 +354,11 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
     }
 
     // surface values for use with ground reactions
-    solid = props->getBoolValue("solid", true);
-    friction_factor = props->getDoubleValue("friction-factor", 1.0);
-    rolling_friction = props->getDoubleValue("rolling-friction", 0.02);
-    bumpiness = props->getDoubleValue("bumpiness", 0.0);
-    load_resistance = props->getDoubleValue("load-resistance", 1e30);
+    _solid = props->getBoolValue("solid", _solid);
+    _friction_factor = props->getDoubleValue("friction-factor", _friction_factor);
+    _rolling_friction = props->getDoubleValue("rolling-friction", _rolling_friction);
+    _bumpiness = props->getDoubleValue("bumpiness", _bumpiness);
+    _load_resistance = props->getDoubleValue("load-resistance", _load_resistance);
 
     // Taken from default values as used in ac3d
     ambient[0] = props->getDoubleValue("ambient/r", 0.2);
@@ -333,6 +398,13 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
         if (name)
             glyphs[name] = new SGMaterialGlyph(glyph_nodes[i]);
     }
+    
+    // Read parameters entry, which is passed into the effect
+    if (props->hasChild("parameters")) {
+        parameters = props->getChild("parameters");
+    } else {
+        parameters = new SGPropertyNode();
+    }
 
     // Read conditions node
     const SGPropertyNode *conditionNode = props->getChild("condition");
@@ -358,12 +430,7 @@ SGMaterial::init ()
 
     mipmap = true;
     light_coverage = 0.0;
-
-    solid = true;
-    friction_factor = 1;
-    rolling_friction = 0.02;
-    bumpiness = 0;
-    load_resistance = 1e30;
+    building_coverage = 0.0;
 
     shininess = 1.0;
     for (int i = 0; i < 4; i++) {
@@ -378,15 +445,17 @@ SGMaterial::init ()
 Effect* SGMaterial::get_effect(int i)
 {    
     if(!_status[i].effect_realized) {
+        if (!_status[i].effect.valid())
+            return 0;
         _status[i].effect->realizeTechniques(_status[i].options.get());
         _status[i].effect_realized = true;
     }
     return _status[i].effect.get();
 }
 
-Effect* SGMaterial::get_effect(SGTexturedTriangleBin triangleBin)
+Effect* SGMaterial::get_effect(const SGTexturedTriangleBin& triangleBin)
 {
-    if (_status.size() == 0) {
+    if (_status.empty()) {
         SG_LOG( SG_GENERAL, SG_WARN, "No effect available.");
         return 0;
     }
@@ -401,9 +470,9 @@ Effect* SGMaterial::get_effect()
 }
 
 
-osg::Texture2D* SGMaterial::get_object_mask(SGTexturedTriangleBin triangleBin)
+osg::Texture2D* SGMaterial::get_object_mask(const SGTexturedTriangleBin& triangleBin)
 {
-    if (_status.size() == 0) {
+    if (_status.empty()) {
         SG_LOG( SG_GENERAL, SG_WARN, "No mask available.");
         return 0;
     }
@@ -424,9 +493,12 @@ void SGMaterial::buildEffectProperties(const SGReaderWriterOptions* options)
     ref_ptr<SGMaterialUserData> user = new SGMaterialUserData(this);
     SGPropertyNode_ptr propRoot = new SGPropertyNode();
     makeChild(propRoot, "inherits-from")->setStringValue(effect);
+    
     SGPropertyNode* paramProp = makeChild(propRoot, "parameters");
+    copyProperties(parameters, paramProp);
+    
     SGPropertyNode* materialProp = makeChild(paramProp, "material");
-    makeChild(materialProp, "ambient")->setValue(SGVec4d(ambient));    
+    makeChild(materialProp, "ambient")->setValue(SGVec4d(ambient));
     makeChild(materialProp, "diffuse")->setValue(SGVec4d(diffuse));
     makeChild(materialProp, "specular")->setValue(SGVec4d(specular));
     makeChild(materialProp, "emissive")->setValue(SGVec4d(emission));
@@ -449,9 +521,9 @@ void SGMaterial::buildEffectProperties(const SGReaderWriterOptions* options)
             makeChild(texProp, "filter")
                 ->setStringValue(mipmap ? "linear-mipmap-linear" : "nearest");
             makeChild(texProp, "wrap-s")
-                ->setStringValue(wrapu ? "repeat" : "clamp");
+                ->setStringValue(wrapu ? "repeat" : "clamp-to-edge");
             makeChild(texProp, "wrap-t")
-                ->setStringValue(wrapv ? "repeat" : "clamp");
+                ->setStringValue(wrapv ? "repeat" : "clamp-to-edge");
         }
         makeChild(effectParamProp, "xsize")->setDoubleValue(xsize);
         makeChild(effectParamProp, "ysize")->setDoubleValue(ysize);
@@ -459,7 +531,8 @@ void SGMaterial::buildEffectProperties(const SGReaderWriterOptions* options)
         makeChild(effectParamProp, "light-coverage")->setDoubleValue(light_coverage);
 
         matState.effect = makeEffect(effectProp, false, options);
-        matState.effect->setUserData(user.get());
+        if (matState.effect.valid())
+            matState.effect->setUserData(user.get());
     }
 }
 
@@ -473,6 +546,15 @@ SGMaterialGlyph* SGMaterial::get_glyph (const string& name) const
     return it->second;
 }
 
+bool SGMaterial::valid() const
+{ 
+  if (condition) {
+    return condition->test();       
+  } else {
+    return true;
+  }
+}
+
 \f
 ////////////////////////////////////////////////////////////////////////
 // SGMaterialGlyph.