Browse Source

Material: allow multiple named techniques

Kirill Vainer 9 years ago
parent
commit
e4f7916301

+ 21 - 37
jme3-core/src/main/java/com/jme3/material/Material.java

@@ -720,46 +720,30 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
         // supports all the caps.
         if (tech == null) {
             EnumSet<Caps> rendererCaps = renderManager.getRenderer().getCaps();
-            if (name.equals("Default")) {
-                List<TechniqueDef> techDefs = def.getDefaultTechniques();
-                if (techDefs == null || techDefs.isEmpty()) {
-                    throw new IllegalArgumentException("No default techniques are available on material '" + def.getName() + "'");
-                }
-
-                TechniqueDef lastTech = null;
-                for (TechniqueDef techDef : techDefs) {
-                    if (rendererCaps.containsAll(techDef.getRequiredCaps())) {
-                        // use the first one that supports all the caps
-                        tech = new Technique(this, techDef);
-                        techniques.put(name, tech);
-                        if(tech.getDef().getLightMode() == renderManager.getPreferredLightMode() ||
-                               tech.getDef().getLightMode() == LightMode.Disable){
-                            break;
-                        }
-                    }
-                    lastTech = techDef;
-                }
-                if (tech == null) {
-                    throw new UnsupportedOperationException("No default technique on material '" + def.getName() + "'\n"
-                            + " is supported by the video hardware. The caps "
-                            + lastTech.getRequiredCaps() + " are required.");
-                }
+            List<TechniqueDef> techDefs = def.getTechniqueDefs(name);
 
-            } else {
-                // create "special" technique instance
-                TechniqueDef techDef = def.getTechniqueDef(name);
-                if (techDef == null) {
-                    throw new IllegalArgumentException("For material " + def.getName() + ", technique not found: " + name);
-                }
+            if (techDefs == null || techDefs.isEmpty()) {
+                throw new IllegalArgumentException(
+                        String.format("The requested technique %s is not available on material %s", name, def.getName()));
+            }
 
-                if (!rendererCaps.containsAll(techDef.getRequiredCaps())) {
-                    throw new UnsupportedOperationException("The explicitly chosen technique '" + name + "' on material '" + def.getName() + "'\n"
-                            + "requires caps " + techDef.getRequiredCaps() + " which are not "
-                            + "supported by the video renderer");
+            TechniqueDef lastTech = null;
+            for (TechniqueDef techDef : techDefs) {
+                if (rendererCaps.containsAll(techDef.getRequiredCaps())) {
+                    // use the first one that supports all the caps
+                    tech = new Technique(this, techDef);
+                    techniques.put(name, tech);
+                    if (tech.getDef().getLightMode() == renderManager.getPreferredLightMode()
+                            || tech.getDef().getLightMode() == LightMode.Disable) {
+                        break;
+                    }
                 }
-
-                tech = new Technique(this, techDef);
-                techniques.put(name, tech);
+                lastTech = techDef;
+            }
+            if (tech == null) {
+                throw new UnsupportedOperationException("No default technique on material '" + def.getName() + "'\n"
+                        + " is supported by the video hardware. The caps "
+                        + lastTech.getRequiredCaps() + " are required.");
             }
         } else if (technique == tech) {
             // attempting to switch to an already

+ 15 - 30
jme3-core/src/main/java/com/jme3/material/MaterialDef.java

@@ -32,6 +32,7 @@
 package com.jme3.material;
 
 import com.jme3.asset.AssetManager;
+import com.jme3.renderer.Caps;
 import com.jme3.shader.VarType;
 import com.jme3.texture.image.ColorSpace;
 import java.util.*;
@@ -51,8 +52,7 @@ public class MaterialDef {
     private String assetName;
     private AssetManager assetManager;
 
-    private List<TechniqueDef> defaultTechs;
-    private Map<String, TechniqueDef> techniques;
+    private Map<String, List<TechniqueDef>> techniques;
     private Map<String, MatParam> matParams;
 
     /**
@@ -70,9 +70,8 @@ public class MaterialDef {
     public MaterialDef(AssetManager assetManager, String name){
         this.assetManager = assetManager;
         this.name = name;
-        techniques = new HashMap<String, TechniqueDef>();
+        techniques = new HashMap<String, List<TechniqueDef>>();
         matParams = new HashMap<String, MatParam>();
-        defaultTechs = new ArrayList<TechniqueDef>();
         logger.log(Level.FINE, "Loaded material definition: {0}", name);
     }
 
@@ -164,40 +163,26 @@ public class MaterialDef {
 
     /**
      * Adds a new technique definition to this material definition.
-     * <p>
-     * If the technique name is "Default", it will be added
-     * to the list of {@link MaterialDef#getDefaultTechniques() default techniques}.
-     * 
+     *
      * @param technique The technique definition to add.
      */
     public void addTechniqueDef(TechniqueDef technique) {
-        if (technique.getName().equals("Default")) {
-            defaultTechs.add(technique);
-        } else {
-            techniques.put(technique.getName(), technique);
+        List<TechniqueDef> list = techniques.get(technique.getName());
+        if (list == null) {
+            list = new ArrayList<>();
+            techniques.put(technique.getName(), list);
         }
+        list.add(technique);
     }
 
     /**
-     * Returns a list of all default techniques.
-     * 
-     * @return a list of all default techniques.
-     */
-    public List<TechniqueDef> getDefaultTechniques(){
-        return defaultTechs;
-    }
-
-    /**
-     * Returns a technique definition with the given name.
-     * This does not include default techniques which can be
-     * retrieved via {@link MaterialDef#getDefaultTechniques() }.
-     * 
-     * @param name The name of the technique definition to find
-     * 
-     * @return The technique definition, or null if cannot be found.
+     * Returns technique definitions with the given name.
+       * 
+     * @param name The name of the technique definitions to find
+       * 
+     * @return The technique definitions, or null if cannot be found.
      */
-    public TechniqueDef getTechniqueDef(String name) {
+    public List<TechniqueDef> getTechniqueDefs(String name) {
         return techniques.get(name);
     }
-
 }

+ 1 - 1
jme3-core/src/main/java/com/jme3/material/TechniqueDef.java

@@ -94,7 +94,7 @@ public class TechniqueDef implements Savable {
         PostPass,
     }
 
-    private EnumSet<Caps> requiredCaps = EnumSet.noneOf(Caps.class);
+    private final EnumSet<Caps> requiredCaps = EnumSet.noneOf(Caps.class);
     private String name;
     private int sortId;
     

+ 2 - 1
jme3-core/src/main/java/com/jme3/renderer/RenderManager.java

@@ -580,7 +580,8 @@ public class RenderManager {
         //if it does not exists in the mat def, we check for forcedMaterial and render the geom if not null
         //else the geom is not rendered
         if (forcedTechnique != null) {
-            if (g.getMaterial().getMaterialDef().getTechniqueDef(forcedTechnique) != null) {
+            MaterialDef matDef = g.getMaterial().getMaterialDef();
+            if (matDef.getTechniqueDefs(forcedTechnique) != null) {
                 tmpTech = g.getMaterial().getActiveTechnique() != null ? g.getMaterial().getActiveTechnique().getDef().getName() : "Default";
                 g.getMaterial().selectTechnique(forcedTechnique, this);
                 //saving forcedRenderState for future calls

+ 1 - 1
jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java

@@ -587,7 +587,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
         for (int i = 0; i < l.size(); i++) {
             Material mat = l.get(i).getMaterial();
             //checking if the material has the post technique and adding it to the material cache
-            if (mat.getMaterialDef().getTechniqueDef(postTechniqueName) != null) {
+            if (mat.getMaterialDef().getTechniqueDefs(postTechniqueName) != null) {
                 if (!matCache.contains(mat)) {
                     matCache.add(mat);
                 }

+ 1 - 1
jme3-core/src/main/java/com/jme3/shadow/PssmShadowRenderer.java

@@ -533,7 +533,7 @@ public class PssmShadowRenderer implements SceneProcessor {
         for (int i = 0; i < l.size(); i++) {
             Material mat = l.get(i).getMaterial();
             //checking if the material has the post technique and adding it to the material cache
-            if (mat.getMaterialDef().getTechniqueDef(postTechniqueName) != null) {
+            if (mat.getMaterialDef().getTechniqueDefs(postTechniqueName) != null) {
                 if (!matCache.contains(mat)) {
                     matCache.add(mat);
                 }

+ 13 - 0
jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java

@@ -7,8 +7,11 @@ import com.jme3.asset.TextureKey;
 import com.jme3.material.MatParamTexture;
 import com.jme3.material.Material;
 import com.jme3.material.MaterialDef;
+import com.jme3.renderer.Caps;
 import com.jme3.shader.VarType;
 import com.jme3.texture.Texture;
+import java.io.IOException;
+import java.util.EnumSet;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -18,6 +21,7 @@ import org.mockito.runners.MockitoJUnitRunner;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.verify;
+import static org.junit.Assert.*;
 import static org.mockito.Mockito.when;
 
 /**
@@ -51,6 +55,15 @@ public class J3MLoaderTest {
         j3MLoader = new J3MLoader();
     }
 
+    @Test
+    public void multipleSameNamedTechniques_shouldBeSupported() throws IOException {
+        when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/same-name-technique.j3md"));
+        MaterialDef def = (MaterialDef) j3MLoader.load(assetInfo);
+        assertEquals(2, def.getTechniqueDefs("Test").size());
+        assertEquals(EnumSet.of(Caps.GLSL150), def.getTechniqueDefs("Test").get(0).getRequiredCaps());
+        assertEquals(EnumSet.of(Caps.GLSL100), def.getTechniqueDefs("Test").get(1).getRequiredCaps());
+    }
+
     @Test
     public void oldStyleTextureParameters_shouldBeSupported() throws Exception {
         when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/texture-parameters-oldstyle.j3m"));

+ 1 - 1
jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java

@@ -38,7 +38,7 @@ public class ShaderCheck {
         MaterialDef def = (MaterialDef) assetManager.loadAsset(matdefName);
         EnumSet<Caps> rendererCaps = EnumSet.noneOf(Caps.class);
         rendererCaps.add(Caps.GLSL100);
-        for (TechniqueDef techDef : def.getDefaultTechniques()) {
+        for (TechniqueDef techDef : def.getTechniqueDefs("Default")) {
             DefineList defines = techDef.createDefineList();
             Shader shader = techDef.getShader(assetManager, rendererCaps, defines);
             for (Validator validator : validators) {