Material has now a isEqual method that compares materialDef, material params and material additional render state
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9256 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
533fb86c50
commit
55b8188d20
engine/src
@ -69,7 +69,6 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
|
||||
// Version #2: Fixed issue with RenderState.apply*** flags not getting exported
|
||||
public static final int SAVABLE_VERSION = 2;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Material.class.getName());
|
||||
private static final RenderState additiveLight = new RenderState();
|
||||
private static final RenderState depthOnly = new RenderState();
|
||||
@ -105,8 +104,8 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
this.def = def;
|
||||
|
||||
// Load default values from definition (if any)
|
||||
for (MatParam param : def.getMaterialParams()){
|
||||
if (param.getValue() != null){
|
||||
for (MatParam param : def.getMaterialParams()) {
|
||||
if (param.getValue() != null) {
|
||||
setParam(param.getName(), param.getVarType(), param.getValue());
|
||||
}
|
||||
}
|
||||
@ -204,8 +203,8 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof Material){
|
||||
return ((Material)obj).compareTo(this) == 0;
|
||||
if (obj instanceof Material) {
|
||||
return ((Material) obj).compareTo(this) == 0;
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
@ -232,10 +231,85 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
|
||||
return mat;
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
throw new AssertionError();
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two materials and returns true if they are equal.
|
||||
* This methods compare definition, params, additional render states
|
||||
* The difference with the equals method is that it's truely comaring the objects. (equals compare the sort ids for geometry sorting)
|
||||
* @param mat the material to cmpare to this material
|
||||
* @return true if the materials are equal.
|
||||
*/
|
||||
public boolean isEqual(Material mat) {
|
||||
//early exit if the material are the same object
|
||||
if (this == mat) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//comparing matrial definition
|
||||
if (this.getMaterialDef() != mat.getMaterialDef()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//early exit if the size of the params is different
|
||||
if (paramValues.size() != mat.paramValues.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//comparing params
|
||||
for (String paramKey : paramValues.keySet()) {
|
||||
MatParam paramOrig = getParam(paramKey);
|
||||
MatParam param = mat.getParam(paramKey);
|
||||
//this param does not exist in compared mat
|
||||
if (param == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//params exist in both materials but they not of the same type
|
||||
if (param.type != paramOrig.type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param instanceof MatParamTexture) {
|
||||
MatParamTexture tex = (MatParamTexture) param;
|
||||
MatParamTexture texOrig = (MatParamTexture) paramOrig;
|
||||
//comparing textures
|
||||
if (getTextureId(tex) != getTextureId(texOrig)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!param.getValue().equals(paramOrig.getValue())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//comparing additional render states
|
||||
if (additionalState == null) {
|
||||
if (mat.additionalState != null) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!additionalState.equals(mat.additionalState)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getTextureId(MatParamTexture param) {
|
||||
if (param.getTextureValue() != null && param.getTextureValue().getImage() != null) {
|
||||
return param.getTextureValue().getImage().getId();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active technique.
|
||||
* <p>
|
||||
@ -386,7 +460,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
|
||||
if (type != null && paramDef.getVarType() != type) {
|
||||
logger.log(Level.WARNING, "Material parameter being set: {0} with "
|
||||
+ "type {1} doesn''t match definition types {2}", new Object[]{name, type.name(), paramDef.getVarType()} );
|
||||
+ "type {1} doesn''t match definition types {2}", new Object[]{name, type.name(), paramDef.getVarType()});
|
||||
}
|
||||
|
||||
return newName;
|
||||
@ -785,7 +859,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
//We transform the spot directoin in view space here to save 5 varying later in the lighting shader
|
||||
//one vec4 less and a vec4 that becomes a vec3
|
||||
//the downside is that spotAngleCos decoding happen now in the frag shader.
|
||||
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(),0);
|
||||
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0);
|
||||
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
|
||||
tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos);
|
||||
|
||||
@ -1064,10 +1138,10 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
boolean guessRenderStateApply = false;
|
||||
|
||||
int ver = ic.getSavableVersion(Material.class);
|
||||
if (ver < 1){
|
||||
if (ver < 1) {
|
||||
applyDefaultValues = true;
|
||||
}
|
||||
if (ver < 2){
|
||||
if (ver < 2) {
|
||||
guessRenderStateApply = true;
|
||||
}
|
||||
if (im.getFormatVersion() == 0) {
|
||||
@ -1118,16 +1192,16 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
|
||||
paramValues.put(param.getName(), param);
|
||||
}
|
||||
|
||||
if (applyDefaultValues){
|
||||
if (applyDefaultValues) {
|
||||
// compatability with old versions where default vars were
|
||||
// not available
|
||||
for (MatParam param : def.getMaterialParams()){
|
||||
if (param.getValue() != null && paramValues.get(param.getName()) == null){
|
||||
for (MatParam param : def.getMaterialParams()) {
|
||||
if (param.getValue() != null && paramValues.get(param.getName()) == null) {
|
||||
setParam(param.getName(), param.getVarType(), param.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (guessRenderStateApply && additionalState != null){
|
||||
if (guessRenderStateApply && additionalState != null) {
|
||||
// Try to guess values of "apply" render state based on defaults
|
||||
// if value != default then set apply to true
|
||||
additionalState.applyPolyOffset = additionalState.offsetEnabled;
|
||||
|
@ -59,13 +59,11 @@ public class RenderState implements Cloneable, Savable {
|
||||
* </ul>
|
||||
*/
|
||||
public static final RenderState DEFAULT = new RenderState();
|
||||
|
||||
/**
|
||||
* The <code>NULL</code> render state is identical to the {@link RenderState#DEFAULT}
|
||||
* render state except that depth testing and face culling are disabled.
|
||||
*/
|
||||
public static final RenderState NULL = new RenderState();
|
||||
|
||||
/**
|
||||
* The <code>ADDITIONAL</code> render state is identical to the
|
||||
* {@link RenderState#DEFAULT} render state except that all apply
|
||||
@ -232,13 +230,11 @@ public class RenderState implements Cloneable, Savable {
|
||||
* Replace the value in the stencil buffer with the reference value.
|
||||
*/
|
||||
Replace,
|
||||
|
||||
/**
|
||||
* Increment the value in the stencil buffer, clamp once reaching
|
||||
* the maximum value.
|
||||
*/
|
||||
Increment,
|
||||
|
||||
/**
|
||||
* Increment the value in the stencil buffer and wrap to 0 when
|
||||
* reaching the maximum value.
|
||||
@ -253,7 +249,6 @@ public class RenderState implements Cloneable, Savable {
|
||||
* value when reaching 0.
|
||||
*/
|
||||
DecrementWrap,
|
||||
|
||||
/**
|
||||
* Does a bitwise invert of the value in the stencil buffer.
|
||||
*/
|
||||
@ -277,39 +272,28 @@ public class RenderState implements Cloneable, Savable {
|
||||
ADDITIONAL.applyAlphaFallOff = false;
|
||||
ADDITIONAL.applyPolyOffset = false;
|
||||
}
|
||||
|
||||
boolean pointSprite = false;
|
||||
boolean applyPointSprite = true;
|
||||
|
||||
boolean wireframe = false;
|
||||
boolean applyWireFrame = true;
|
||||
|
||||
FaceCullMode cullMode = FaceCullMode.Back;
|
||||
boolean applyCullMode = true;
|
||||
|
||||
boolean depthWrite = true;
|
||||
boolean applyDepthWrite = true;
|
||||
|
||||
boolean depthTest = true;
|
||||
boolean applyDepthTest = true;
|
||||
|
||||
boolean colorWrite = true;
|
||||
boolean applyColorWrite = true;
|
||||
|
||||
BlendMode blendMode = BlendMode.Off;
|
||||
boolean applyBlendMode = true;
|
||||
|
||||
boolean alphaTest = false;
|
||||
boolean applyAlphaTest = true;
|
||||
|
||||
float alphaFallOff = 0;
|
||||
boolean applyAlphaFallOff = true;
|
||||
|
||||
float offsetFactor = 0;
|
||||
float offsetUnits = 0;
|
||||
boolean offsetEnabled = false;
|
||||
boolean applyPolyOffset = true;
|
||||
|
||||
boolean stencilTest = false;
|
||||
boolean applyStencilTest = false;
|
||||
StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep;
|
||||
@ -409,6 +393,103 @@ public class RenderState implements Cloneable, Savable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the given renderState is equall to this one
|
||||
* @param o the renderState to compate to
|
||||
* @return true if the renderStates are equal
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(o instanceof RenderState)) {
|
||||
return false;
|
||||
}
|
||||
RenderState rs = (RenderState) o;
|
||||
if (pointSprite != rs.pointSprite) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wireframe != rs.wireframe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cullMode != rs.cullMode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (depthWrite != rs.depthWrite) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (depthTest != rs.depthTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (colorWrite != rs.colorWrite) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blendMode != rs.blendMode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (alphaTest != rs.alphaTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (alphaFallOff != rs.alphaFallOff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offsetEnabled != rs.offsetEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offsetFactor != rs.offsetFactor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offsetUnits != rs.offsetUnits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stencilTest != rs.stencilTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stencilTest) {
|
||||
if (frontStencilStencilFailOperation != rs.frontStencilStencilFailOperation) {
|
||||
return false;
|
||||
}
|
||||
if (frontStencilDepthFailOperation != rs.frontStencilDepthFailOperation) {
|
||||
return false;
|
||||
}
|
||||
if (frontStencilDepthPassOperation != rs.frontStencilDepthPassOperation) {
|
||||
return false;
|
||||
}
|
||||
if (backStencilStencilFailOperation != rs.backStencilStencilFailOperation) {
|
||||
return false;
|
||||
}
|
||||
if (backStencilDepthFailOperation != rs.backStencilDepthFailOperation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (backStencilDepthPassOperation != rs.backStencilDepthPassOperation) {
|
||||
return false;
|
||||
}
|
||||
if (frontStencilFunction != rs.frontStencilFunction) {
|
||||
return false;
|
||||
}
|
||||
if (backStencilFunction != rs.backStencilFunction) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables point sprite mode.
|
||||
*
|
||||
@ -1033,7 +1114,7 @@ public class RenderState implements Cloneable, Savable {
|
||||
state.offsetFactor = offsetFactor;
|
||||
state.offsetUnits = offsetUnits;
|
||||
}
|
||||
if (additionalState.applyStencilTest){
|
||||
if (additionalState.applyStencilTest) {
|
||||
state.stencilTest = additionalState.stencilTest;
|
||||
|
||||
state.frontStencilStencilFailOperation = additionalState.frontStencilStencilFailOperation;
|
||||
@ -1046,7 +1127,7 @@ public class RenderState implements Cloneable, Savable {
|
||||
|
||||
state.frontStencilFunction = additionalState.frontStencilFunction;
|
||||
state.backStencilFunction = additionalState.backStencilFunction;
|
||||
}else{
|
||||
} else {
|
||||
state.stencilTest = stencilTest;
|
||||
|
||||
state.frontStencilStencilFailOperation = frontStencilStencilFailOperation;
|
||||
|
109
engine/src/test/jme3test/material/TestMaterialCompare.java
Normal file
109
engine/src/test/jme3test/material/TestMaterialCompare.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jme3test.material;
|
||||
|
||||
import com.jme3.app.SimpleApplication;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.material.RenderState.BlendMode;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class TestMaterialCompare extends SimpleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestMaterialCompare app = new TestMaterialCompare();
|
||||
app.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simpleInitApp() {
|
||||
|
||||
Logger.getLogger("com.jme3").setLevel(Level.SEVERE);
|
||||
|
||||
//clonned mats
|
||||
Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
mat1.setName("mat1");
|
||||
mat1.setColor("Color", ColorRGBA.Blue);
|
||||
|
||||
Material mat2 = mat1.clone();
|
||||
mat2.setName("mat2");
|
||||
testMats(mat1,mat2,true);
|
||||
|
||||
//clonned mat with different additional render state
|
||||
Material mat3 = mat1.clone();;
|
||||
mat3.setName("mat3");
|
||||
mat3.getAdditionalRenderState().setBlendMode(BlendMode.ModulateX2);
|
||||
testMats(mat1,mat3,false);
|
||||
|
||||
//two separately loaded materials
|
||||
Material mat4 = assetManager.loadMaterial("Models/Sign Post/Sign Post.j3m");
|
||||
mat4.setName("mat4");
|
||||
Material mat5 = assetManager.loadMaterial("Models/Sign Post/Sign Post.j3m");
|
||||
mat5.setName("mat5");
|
||||
testMats(mat4,mat5,true);
|
||||
|
||||
//two materials created the same way
|
||||
Material mat6 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
mat6.setName("mat6");
|
||||
mat6.setColor("Color", ColorRGBA.Blue);
|
||||
testMats(mat1,mat6,true);
|
||||
|
||||
//changing a material param
|
||||
mat6.setColor("Color", ColorRGBA.Green);
|
||||
testMats(mat1,mat6,false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void testMats(Material mat1, Material mat2, boolean expected) {
|
||||
if (mat2.isEqual(mat1)) {
|
||||
System.out.print(mat1.getName() + " equals " + mat2.getName());
|
||||
if(expected){
|
||||
System.out.println(" success");
|
||||
}else{
|
||||
System.out.println(" fail");
|
||||
}
|
||||
}else{
|
||||
System.out.print(mat1.getName() + " is not equal " + mat2.getName());
|
||||
if(!expected){
|
||||
System.out.println(" success");
|
||||
}else{
|
||||
System.out.println(" fail");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simpleUpdate(float tpf) {
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user