From e4f7916301dd837f58b95a2ffd6899dc100eb561 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Fri, 8 Apr 2016 23:31:39 -0400 Subject: [PATCH] Material: allow multiple named techniques --- .../main/java/com/jme3/material/Material.java | 58 +++++++------------ .../java/com/jme3/material/MaterialDef.java | 45 +++++--------- .../java/com/jme3/material/TechniqueDef.java | 2 +- .../java/com/jme3/renderer/RenderManager.java | 3 +- .../jme3/shadow/AbstractShadowRenderer.java | 2 +- .../com/jme3/shadow/PssmShadowRenderer.java | 2 +- .../jme3/material/plugins/J3MLoaderTest.java | 13 +++++ .../jme3tools/shadercheck/ShaderCheck.java | 2 +- 8 files changed, 55 insertions(+), 72 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/material/Material.java b/jme3-core/src/main/java/com/jme3/material/Material.java index 1fe8bac06..73e103659 100644 --- a/jme3-core/src/main/java/com/jme3/material/Material.java +++ b/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 rendererCaps = renderManager.getRenderer().getCaps(); - if (name.equals("Default")) { - List 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 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 diff --git a/jme3-core/src/main/java/com/jme3/material/MaterialDef.java b/jme3-core/src/main/java/com/jme3/material/MaterialDef.java index 21eac324c..fa205460e 100644 --- a/jme3-core/src/main/java/com/jme3/material/MaterialDef.java +++ b/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 defaultTechs; - private Map techniques; + private Map> techniques; private Map matParams; /** @@ -70,9 +70,8 @@ public class MaterialDef { public MaterialDef(AssetManager assetManager, String name){ this.assetManager = assetManager; this.name = name; - techniques = new HashMap(); + techniques = new HashMap>(); matParams = new HashMap(); - defaultTechs = new ArrayList(); 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. - *

- * 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 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 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 getTechniqueDefs(String name) { return techniques.get(name); } - } diff --git a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java index 6f499b271..c954a1469 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -94,7 +94,7 @@ public class TechniqueDef implements Savable { PostPass, } - private EnumSet requiredCaps = EnumSet.noneOf(Caps.class); + private final EnumSet requiredCaps = EnumSet.noneOf(Caps.class); private String name; private int sortId; diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderManager.java b/jme3-core/src/main/java/com/jme3/renderer/RenderManager.java index 45b118926..bdfe33fd6 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderManager.java +++ b/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 diff --git a/jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java index b55c6b2d2..891c3b402 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java +++ b/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); } diff --git a/jme3-core/src/main/java/com/jme3/shadow/PssmShadowRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/PssmShadowRenderer.java index e06b5c337..ed84f9f0c 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/PssmShadowRenderer.java +++ b/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); } diff --git a/jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java b/jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java index b50104092..9f9a1fded 100644 --- a/jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java +++ b/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")); diff --git a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java b/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java index d41dde064..e409caa53 100644 --- a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java +++ b/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java @@ -38,7 +38,7 @@ public class ShaderCheck { MaterialDef def = (MaterialDef) assetManager.loadAsset(matdefName); EnumSet 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) {