1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.material; 33 34 import com.jme3.asset.TextureKey; 35 import com.jme3.export.*; 36 import com.jme3.math.*; 37 import com.jme3.renderer.GL1Renderer; 38 import com.jme3.renderer.Renderer; 39 import com.jme3.shader.VarType; 40 import com.jme3.texture.Texture; 41 import com.jme3.texture.Texture.WrapMode; 42 import java.io.IOException; 43 44 /** 45 * Describes a material parameter. This is used for both defining a name and type 46 * as well as a material parameter value. 47 * 48 * @author Kirill Vainer 49 */ 50 public class MatParam implements Savable, Cloneable { 51 52 protected VarType type; 53 protected String name; 54 protected String prefixedName; 55 protected Object value; 56 protected FixedFuncBinding ffBinding; 57 58 /** 59 * Create a new material parameter. For internal use only. 60 */ MatParam(VarType type, String name, Object value, FixedFuncBinding ffBinding)61 public MatParam(VarType type, String name, Object value, FixedFuncBinding ffBinding) { 62 this.type = type; 63 this.name = name; 64 this.prefixedName = "m_" + name; 65 this.value = value; 66 this.ffBinding = ffBinding; 67 } 68 69 /** 70 * Serialization only. Do not use. 71 */ MatParam()72 public MatParam() { 73 } 74 75 /** 76 * Returns the fixed function binding. 77 * 78 * @return the fixed function binding. 79 */ getFixedFuncBinding()80 public FixedFuncBinding getFixedFuncBinding() { 81 return ffBinding; 82 } 83 84 /** 85 * Returns the material parameter type. 86 * 87 * @return the material parameter type. 88 */ getVarType()89 public VarType getVarType() { 90 return type; 91 } 92 93 /** 94 * Returns the name of the material parameter. 95 * @return the name of the material parameter. 96 */ getName()97 public String getName() { 98 return name; 99 } 100 101 /** 102 * Returns the name with "m_" prefixed to it. 103 * 104 * @return the name with "m_" prefixed to it 105 */ getPrefixedName()106 public String getPrefixedName() { 107 return prefixedName; 108 } 109 110 /** 111 * Used internally 112 * @param name 113 */ setName(String name)114 void setName(String name) { 115 this.name = name; 116 this.prefixedName = "m_" + name; 117 } 118 119 /** 120 * Returns the value of this material parameter. 121 * <p> 122 * Material parameters that are used for material definitions 123 * will not have a value, unless there's a default value declared 124 * in the definition. 125 * 126 * @return the value of this material parameter. 127 */ getValue()128 public Object getValue() { 129 return value; 130 } 131 132 /** 133 * Sets the value of this material parameter. 134 * <p> 135 * It is assumed the value is of the same {@link MatParam#getVarType() type} 136 * as this material parameter. 137 * 138 * @param value the value of this material parameter. 139 */ setValue(Object value)140 public void setValue(Object value) { 141 this.value = value; 142 } 143 apply(Renderer r, Technique technique)144 void apply(Renderer r, Technique technique) { 145 TechniqueDef techDef = technique.getDef(); 146 if (techDef.isUsingShaders()) { 147 technique.updateUniformParam(getPrefixedName(), getVarType(), getValue(), true); 148 } 149 if (ffBinding != null && r instanceof GL1Renderer) { 150 ((GL1Renderer) r).setFixedFuncBinding(ffBinding, getValue()); 151 } 152 } 153 154 /** 155 * Returns the material parameter value as it would appear in a J3M 156 * file. E.g.<br/> 157 * <code> 158 * MaterialParameters {<br/> 159 * ABC : 1 2 3 4<br/> 160 * }<br/> 161 * </code> 162 * Assuming "ABC" is a Vector4 parameter, then the value 163 * "1 2 3 4" would be returned by this method. 164 * <br/><br/> 165 * @return material parameter value as it would appear in a J3M file. 166 */ getValueAsString()167 public String getValueAsString() { 168 switch (type) { 169 case Boolean: 170 case Float: 171 case Int: 172 return value.toString(); 173 case Vector2: 174 Vector2f v2 = (Vector2f) value; 175 return v2.getX() + " " + v2.getY(); 176 /* 177 This may get used at a later point of time 178 When arrays can be inserted in J3M files 179 180 case Vector2Array: 181 Vector2f[] v2Arr = (Vector2f[]) value; 182 String v2str = ""; 183 for (int i = 0; i < v2Arr.length ; i++) { 184 v2str += v2Arr[i].getX() + " " + v2Arr[i].getY() + "\n"; 185 } 186 return v2str; 187 */ 188 case Vector3: 189 Vector3f v3 = (Vector3f) value; 190 return v3.getX() + " " + v3.getY() + " " + v3.getZ(); 191 /* 192 case Vector3Array: 193 Vector3f[] v3Arr = (Vector3f[]) value; 194 String v3str = ""; 195 for (int i = 0; i < v3Arr.length ; i++) { 196 v3str += v3Arr[i].getX() + " " 197 + v3Arr[i].getY() + " " 198 + v3Arr[i].getZ() + "\n"; 199 } 200 return v3str; 201 case Vector4Array: 202 // can be either ColorRGBA, Vector4f or Quaternion 203 if (value instanceof Vector4f) { 204 Vector4f[] v4arr = (Vector4f[]) value; 205 String v4str = ""; 206 for (int i = 0; i < v4arr.length ; i++) { 207 v4str += v4arr[i].getX() + " " 208 + v4arr[i].getY() + " " 209 + v4arr[i].getZ() + " " 210 + v4arr[i].getW() + "\n"; 211 } 212 return v4str; 213 } else if (value instanceof ColorRGBA) { 214 ColorRGBA[] colorArr = (ColorRGBA[]) value; 215 String colStr = ""; 216 for (int i = 0; i < colorArr.length ; i++) { 217 colStr += colorArr[i].getRed() + " " 218 + colorArr[i].getGreen() + " " 219 + colorArr[i].getBlue() + " " 220 + colorArr[i].getAlpha() + "\n"; 221 } 222 return colStr; 223 } else if (value instanceof Quaternion) { 224 Quaternion[] quatArr = (Quaternion[]) value; 225 String quatStr = ""; 226 for (int i = 0; i < quatArr.length ; i++) { 227 quatStr += quatArr[i].getX() + " " 228 + quatArr[i].getY() + " " 229 + quatArr[i].getZ() + " " 230 + quatArr[i].getW() + "\n"; 231 } 232 return quatStr; 233 } else { 234 throw new UnsupportedOperationException("Unexpected Vector4Array type: " + value); 235 } 236 */ 237 case Vector4: 238 // can be either ColorRGBA, Vector4f or Quaternion 239 if (value instanceof Vector4f) { 240 Vector4f v4 = (Vector4f) value; 241 return v4.getX() + " " + v4.getY() + " " 242 + v4.getZ() + " " + v4.getW(); 243 } else if (value instanceof ColorRGBA) { 244 ColorRGBA color = (ColorRGBA) value; 245 return color.getRed() + " " + color.getGreen() + " " 246 + color.getBlue() + " " + color.getAlpha(); 247 } else if (value instanceof Quaternion) { 248 Quaternion quat = (Quaternion) value; 249 return quat.getX() + " " + quat.getY() + " " 250 + quat.getZ() + " " + quat.getW(); 251 } else { 252 throw new UnsupportedOperationException("Unexpected Vector4 type: " + value); 253 } 254 case Texture2D: 255 case Texture3D: 256 case TextureArray: 257 case TextureBuffer: 258 case TextureCubeMap: 259 Texture texVal = (Texture) value; 260 TextureKey texKey = (TextureKey) texVal.getKey(); 261 if (texKey == null){ 262 throw new UnsupportedOperationException("The specified MatParam cannot be represented in J3M"); 263 } 264 265 String ret = ""; 266 if (texKey.isFlipY()) { 267 ret += "Flip "; 268 } 269 if (texVal.getWrap(Texture.WrapAxis.S) == WrapMode.Repeat) { 270 ret += "Repeat "; 271 } 272 273 return ret + texKey.getName(); 274 default: 275 return null; // parameter type not supported in J3M 276 } 277 } 278 279 @Override clone()280 public MatParam clone() { 281 try { 282 MatParam param = (MatParam) super.clone(); 283 return param; 284 } catch (CloneNotSupportedException ex) { 285 throw new AssertionError(); 286 } 287 } 288 write(JmeExporter ex)289 public void write(JmeExporter ex) throws IOException { 290 OutputCapsule oc = ex.getCapsule(this); 291 oc.write(type, "varType", null); 292 oc.write(name, "name", null); 293 oc.write(ffBinding, "ff_binding", null); 294 if (value instanceof Savable) { 295 Savable s = (Savable) value; 296 oc.write(s, "value_savable", null); 297 } else if (value instanceof Float) { 298 Float f = (Float) value; 299 oc.write(f.floatValue(), "value_float", 0f); 300 } else if (value instanceof Integer) { 301 Integer i = (Integer) value; 302 oc.write(i.intValue(), "value_int", 0); 303 } else if (value instanceof Boolean) { 304 Boolean b = (Boolean) value; 305 oc.write(b.booleanValue(), "value_bool", false); 306 } 307 } 308 read(JmeImporter im)309 public void read(JmeImporter im) throws IOException { 310 InputCapsule ic = im.getCapsule(this); 311 type = ic.readEnum("varType", VarType.class, null); 312 name = ic.readString("name", null); 313 ffBinding = ic.readEnum("ff_binding", FixedFuncBinding.class, null); 314 switch (getVarType()) { 315 case Boolean: 316 value = ic.readBoolean("value_bool", false); 317 break; 318 case Float: 319 value = ic.readFloat("value_float", 0f); 320 break; 321 case Int: 322 value = ic.readInt("value_int", 0); 323 break; 324 default: 325 value = ic.readSavable("value_savable", null); 326 break; 327 } 328 } 329 330 @Override equals(Object other)331 public boolean equals(Object other) { 332 if (!(other instanceof MatParam)) { 333 return false; 334 } 335 336 MatParam otherParam = (MatParam) other; 337 return otherParam.type == type 338 && otherParam.name.equals(name); 339 } 340 341 @Override hashCode()342 public int hashCode() { 343 int hash = 5; 344 hash = 17 * hash + (this.type != null ? this.type.hashCode() : 0); 345 hash = 17 * hash + (this.name != null ? this.name.hashCode() : 0); 346 return hash; 347 } 348 349 @Override toString()350 public String toString() { 351 return type.name() + " " + name + " : " + getValueAsString(); 352 } 353 } 354