11/*
2- * Copyright (c) 2009-2024 jMonkeyEngine
2+ * Copyright (c) 2009-2025 jMonkeyEngine
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
3434import com .jme3 .asset .AssetKey ;
3535import com .jme3 .asset .AssetManager ;
3636import com .jme3 .asset .CloneableSmartAsset ;
37- import com .jme3 .export .*;
37+ import com .jme3 .export .InputCapsule ;
38+ import com .jme3 .export .JmeExporter ;
39+ import com .jme3 .export .JmeImporter ;
40+ import com .jme3 .export .OutputCapsule ;
41+ import com .jme3 .export .Savable ;
3842import com .jme3 .light .LightList ;
3943import com .jme3 .material .RenderState .BlendMode ;
4044import com .jme3 .material .RenderState .FaceCullMode ;
4145import com .jme3 .material .TechniqueDef .LightMode ;
42- import com .jme3 .math .*;
46+ import com .jme3 .math .ColorRGBA ;
47+ import com .jme3 .math .Matrix4f ;
48+ import com .jme3 .math .Vector2f ;
49+ import com .jme3 .math .Vector3f ;
50+ import com .jme3 .math .Vector4f ;
4351import com .jme3 .renderer .Caps ;
4452import com .jme3 .renderer .RenderManager ;
4553import com .jme3 .renderer .Renderer ;
5664import com .jme3 .util .SafeArrayList ;
5765
5866import java .io .IOException ;
59- import java .util .*;
67+ import java .util .Collection ;
68+ import java .util .EnumSet ;
69+ import java .util .HashMap ;
70+ import java .util .List ;
71+ import java .util .Map ;
6072import java .util .logging .Level ;
6173import java .util .logging .Logger ;
6274
@@ -77,7 +89,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
7789 public static final int SAVABLE_VERSION = 2 ;
7890 private static final Logger logger = Logger .getLogger (Material .class .getName ());
7991
80- private AssetKey key ;
92+ private AssetKey <?> key ;
8193 private String name ;
8294 private MaterialDef def ;
8395 private ListMap <String , MatParam > paramValues = new ListMap <>();
@@ -90,15 +102,24 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
90102 private int sortingId = -1 ;
91103
92104 /**
93- * Track bind ids for textures and buffers
94- * Used internally
105+ * Manages and tracks texture and buffer binding units for rendering.
106+ * Used internally by the Material class.
95107 */
96108 public static class BindUnits {
109+ /** The current texture unit counter. */
97110 public int textureUnit = 0 ;
111+ /** The current buffer unit counter. */
98112 public int bufferUnit = 0 ;
99113 }
100114 private BindUnits bindUnits = new BindUnits ();
101115
116+ /**
117+ * Constructs a new Material instance based on a provided MaterialDef.
118+ * The material's parameters will be initialized with default values from the definition.
119+ *
120+ * @param def The material definition to use (cannot be null).
121+ * @throws IllegalArgumentException if def is null.
122+ */
102123 public Material (MaterialDef def ) {
103124 if (def == null ) {
104125 throw new IllegalArgumentException ("Material definition cannot be null" );
@@ -113,40 +134,48 @@ public Material(MaterialDef def) {
113134 }
114135 }
115136
116- public Material (AssetManager contentMan , String defName ) {
117- this (contentMan .loadAsset (new AssetKey <MaterialDef >(defName )));
137+ /**
138+ * Constructs a new Material by loading its MaterialDef from the asset manager.
139+ *
140+ * @param assetManager The asset manager to load the MaterialDef from.
141+ * @param defName The asset path of the .j3md file.
142+ */
143+ public Material (AssetManager assetManager , String defName ) {
144+ this (assetManager .loadAsset (new AssetKey <MaterialDef >(defName )));
118145 }
119146
120147 /**
121- * Do not use this constructor. Serialization purposes only .
148+ * For serialization only. Do not use .
122149 */
123150 public Material () {
124151 }
125152
126153 /**
127154 * Returns the asset key name of the asset from which this material was loaded.
155+ * <p>This value will be null unless this material was loaded from a .j3m file.</p>
128156 *
129- * <p>This value will be <code>null</code> unless this material was loaded
130- * from a .j3m file.
131- *
132- * @return Asset key name of the j3m file
157+ * @return Asset key name of the .j3m file, or null if not loaded from a file.
133158 */
134159 public String getAssetName () {
135160 return key != null ? key .getName () : null ;
136161 }
137162
138163 /**
139- * @return the name of the material (not the same as the asset name), the returned value can be null
164+ * Returns the user-defined name of the material.
165+ * This name is distinct from the asset name and may be null or not unique.
166+ *
167+ * @return The name of the material, or null.
140168 */
141169 public String getName () {
142170 return name ;
143171 }
144172
145173 /**
146- * This method sets the name of the material.
174+ * Sets the user-defined name of the material.
147175 * The name is not the same as the asset name.
148- * It can be null and there is no guarantee of its uniqueness.
149- * @param name the name of the material
176+ * It can be null, and there is no guarantee of its uniqueness.
177+ *
178+ * @param name The name of the material.
150179 */
151180 public void setName (String name ) {
152181 this .name = name ;
@@ -228,7 +257,7 @@ public Material clone() {
228257 }
229258
230259 /**
231- * Compares two materials and returns true if they are equal .
260+ * Compares two materials for content equality .
232261 * This methods compare definition, parameters, additional render states.
233262 * Since materials are mutable objects, implementing equals() properly is not possible,
234263 * hence the name contentEquals().
@@ -405,7 +434,7 @@ public RenderState getAdditionalRenderState() {
405434 }
406435
407436 /**
408- * Get the material definition (j3md file info) that <code>this</code>
437+ * Get the material definition (. j3md file info) that <code>this</code>
409438 * material is implementing.
410439 *
411440 * @return the material definition this material implements.
@@ -494,7 +523,7 @@ private void checkSetParam(VarType type, String name) {
494523 /**
495524 * Pass a parameter to the material shader.
496525 *
497- * @param name the name of the parameter defined in the material definition (j3md)
526+ * @param name the name of the parameter defined in the material definition (. j3md)
498527 * @param type the type of the parameter {@link VarType}
499528 * @param value the value of the parameter
500529 */
@@ -506,7 +535,6 @@ public void setParam(String name, VarType type, Object value) {
506535 } else {
507536 MatParam val = getParam (name );
508537 if (val == null ) {
509- MatParam paramDef = def .getMaterialParam (name );
510538 paramValues .put (name , new MatParam (type , name , value ));
511539 } else {
512540 val .setValue (value );
@@ -533,7 +561,6 @@ public void setParam(String name, Object value) {
533561 setParam (name , p .getVarType (), value );
534562 }
535563
536-
537564 /**
538565 * Clear a parameter from this material. The parameter must exist
539566 * @param name the name of the parameter to clear
@@ -569,14 +596,17 @@ public void setTextureParam(String name, VarType type, Texture value) {
569596 }
570597
571598 checkSetParam (type , name );
572- MatParamTexture val = getTextureParam (name );
573- if (val == null ) {
574- checkTextureParamColorSpace (name , value );
575- paramValues .put (name , new MatParamTexture (type , name , value , value .getImage () != null ? value .getImage ().getColorSpace () : null ));
599+ MatParamTexture param = getTextureParam (name );
600+
601+ checkTextureParamColorSpace (name , value );
602+ ColorSpace colorSpace = value .getImage () != null ? value .getImage ().getColorSpace () : null ;
603+
604+ if (param == null ) {
605+ param = new MatParamTexture (type , name , value , colorSpace );
606+ paramValues .put (name , param );
576607 } else {
577- checkTextureParamColorSpace (name , value );
578- val .setTextureValue (value );
579- val .setColorSpace (value .getImage () != null ? value .getImage ().getColorSpace () : null );
608+ param .setTextureValue (value );
609+ param .setColorSpace (colorSpace );
580610 }
581611
582612 if (technique != null ) {
@@ -613,8 +643,8 @@ private void checkTextureParamColorSpace(String name, Texture value) {
613643 /**
614644 * Pass a texture to the material shader.
615645 *
616- * @param name the name of the texture defined in the material definition
617- * ( j3md) (for example Texture for Lighting.j3md)
646+ * @param name the name of the texture defined in the material definition
647+ * (. j3md) (e.g. Texture for Lighting.j3md)
618648 * @param value the Texture object previously loaded by the asset manager
619649 */
620650 public void setTexture (String name , Texture value ) {
@@ -707,7 +737,7 @@ public void setColor(String name, ColorRGBA value) {
707737 }
708738
709739 /**
710- * Pass an uniform buffer object to the material shader.
740+ * Pass a uniform buffer object to the material shader.
711741 *
712742 * @param name the name of the buffer object defined in the material definition (j3md).
713743 * @param value the buffer object.
@@ -843,7 +873,6 @@ private void applyOverrides(Renderer renderer, Shader shader, SafeArrayList<MatP
843873 }
844874 }
845875
846-
847876 private void updateShaderMaterialParameter (Renderer renderer , VarType type , Shader shader , MatParam param , BindUnits unit , boolean override ) {
848877 if (type == VarType .UniformBufferObject || type == VarType .ShaderStorageBufferObject ) {
849878 ShaderBufferBlock bufferBlock = shader .getBufferBlock (param .getPrefixedName ());
@@ -862,7 +891,8 @@ private void updateShaderMaterialParameter(Renderer renderer, VarType type, Shad
862891 unit .bufferUnit ++;
863892 } else {
864893 Uniform uniform = shader .getUniform (param .getPrefixedName ());
865- if (!override && uniform .isSetByCurrentMaterial ()) return ;
894+ if (!override && uniform .isSetByCurrentMaterial ())
895+ return ;
866896
867897 if (type .isTextureType () || type .isImageType ()) {
868898 try {
@@ -871,9 +901,9 @@ private void updateShaderMaterialParameter(Renderer renderer, VarType type, Shad
871901 } else {
872902 renderer .setTextureImage (unit .textureUnit , (TextureImage ) param .getValue ());
873903 }
874- } catch (TextureUnitException exception ) {
904+ } catch (TextureUnitException ex ) {
875905 int numTexParams = unit .textureUnit + 1 ;
876- String message = "Too many texture parameters (" + numTexParams + ") assigned\n to " + toString ();
906+ String message = "Too many texture parameters (" + numTexParams + ") assigned\n to " + this . toString ();
877907 throw new IllegalStateException (message );
878908 }
879909 uniform .setValue (VarType .Int , unit .textureUnit );
@@ -884,11 +914,8 @@ private void updateShaderMaterialParameter(Renderer renderer, VarType type, Shad
884914 }
885915 }
886916
887-
888-
889-
890- private BindUnits updateShaderMaterialParameters (Renderer renderer , Shader shader , SafeArrayList <MatParamOverride > worldOverrides ,
891- SafeArrayList <MatParamOverride > forcedOverrides ) {
917+ private BindUnits updateShaderMaterialParameters (Renderer renderer , Shader shader ,
918+ SafeArrayList <MatParamOverride > worldOverrides , SafeArrayList <MatParamOverride > forcedOverrides ) {
892919
893920 bindUnits .textureUnit = 0 ;
894921 bindUnits .bufferUnit = 0 ;
@@ -901,20 +928,15 @@ private BindUnits updateShaderMaterialParameters(Renderer renderer, Shader shade
901928 }
902929
903930 for (int i = 0 ; i < paramValues .size (); i ++) {
904-
905931 MatParam param = paramValues .getValue (i );
906932 VarType type = param .getVarType ();
907-
908933 updateShaderMaterialParameter (renderer , type , shader , param , bindUnits , false );
909934 }
910935
911- // TODO HACKY HACK remove this when texture unit is handled by the
912- // uniform.
936+ // TODO: HACKY HACK remove this when texture unit is handled by the uniform.
913937 return bindUnits ;
914938 }
915939
916-
917-
918940 private void updateRenderState (Geometry geometry , RenderManager renderManager , Renderer renderer , TechniqueDef techniqueDef ) {
919941 RenderState finalRenderState ;
920942 if (renderManager .getForcedRenderState () != null ) {
@@ -935,8 +957,9 @@ private void updateRenderState(Geometry geometry, RenderManager renderManager, R
935957
936958 /**
937959 * Returns true if the geometry world scale indicates that normals will be backward.
938- * @param scalar geometry world scale
939- * @return
960+ *
961+ * @param scalar The geometry's world scale vector.
962+ * @return true if the normals are effectively backward; false otherwise.
940963 */
941964 private boolean isNormalsBackward (Vector3f scalar ) {
942965 // count number of negative scalar vector components
@@ -1113,6 +1136,14 @@ public void render(Geometry geom, RenderManager rm) {
11131136 render (geom , geom .getWorldLightList (), rm );
11141137 }
11151138
1139+ @ Override
1140+ public String toString () {
1141+ return "Material[name=" + name +
1142+ ", def=" + (def != null ? def .getName () : null ) +
1143+ ", tech=" + (technique != null && technique .getDef () != null ? technique .getDef ().getName () : null ) +
1144+ "]" ;
1145+ }
1146+
11161147 @ Override
11171148 public void write (JmeExporter ex ) throws IOException {
11181149 OutputCapsule oc = ex .getCapsule (this );
@@ -1123,14 +1154,6 @@ public void write(JmeExporter ex) throws IOException {
11231154 oc .writeStringSavableMap (paramValues , "parameters" , null );
11241155 }
11251156
1126- @ Override
1127- public String toString () {
1128- return "Material[name=" + name +
1129- ", def=" + (def != null ? def .getName () : null ) +
1130- ", tech=" + (technique != null && technique .getDef () != null ? technique .getDef ().getName () : null ) +
1131- "]" ;
1132- }
1133-
11341157 @ Override
11351158 @ SuppressWarnings ("unchecked" )
11361159 public void read (JmeImporter im ) throws IOException {
@@ -1144,7 +1167,7 @@ public void read(JmeImporter im) throws IOException {
11441167 String defName = ic .readString ("material_def" , null );
11451168 HashMap <String , MatParam > params = (HashMap <String , MatParam >) ic .readStringSavableMap ("parameters" , null );
11461169
1147- boolean enableVcolor = false ;
1170+ boolean enableVertexColor = false ;
11481171 boolean separateTexCoord = false ;
11491172 boolean applyDefaultValues = false ;
11501173 boolean guessRenderStateApply = false ;
@@ -1160,7 +1183,7 @@ public void read(JmeImporter im) throws IOException {
11601183 // Enable compatibility with old models
11611184 if (defName .equalsIgnoreCase ("Common/MatDefs/Misc/VertexColor.j3md" )) {
11621185 // Using VertexColor, switch to Unshaded and set VertexColor=true
1163- enableVcolor = true ;
1186+ enableVertexColor = true ;
11641187 defName = "Common/MatDefs/Misc/Unshaded.j3md" ;
11651188 } else if (defName .equalsIgnoreCase ("Common/MatDefs/Misc/SimpleTextured.j3md" )
11661189 || defName .equalsIgnoreCase ("Common/MatDefs/Misc/SolidColor.j3md" )) {
@@ -1212,8 +1235,7 @@ public void read(JmeImporter im) throws IOException {
12121235 }
12131236
12141237 if (applyDefaultValues ) {
1215- // compatability with old versions where default vars were
1216- // not available
1238+ // compatibility with old versions where default vars were not available
12171239 for (MatParam param : def .getMaterialParams ()) {
12181240 if (param .getValue () != null && paramValues .get (param .getName ()) == null ) {
12191241 setParam (param .getName (), param .getVarType (), param .getValue ());
@@ -1232,7 +1254,7 @@ public void read(JmeImporter im) throws IOException {
12321254 additionalState .applyStencilTest = additionalState .stencilTest ;
12331255 additionalState .applyWireFrame = additionalState .wireframe ;
12341256 }
1235- if (enableVcolor ) {
1257+ if (enableVertexColor ) {
12361258 setBoolean ("VertexColor" , true );
12371259 }
12381260 if (separateTexCoord ) {
0 commit comments