/*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package javax.media.j3d;
import javax.vecmath.Color3f;
/**
* The Material object defines the appearance of an object under
* illumination.
* If the Material object in an Appearance object is null
,
* lighting is disabled for all nodes that use that Appearance object.
*
* The properties that can be set for a Material object are:
*
* - Ambient color - the ambient RGB color reflected off the surface
* of the material. The range of values is 0.0 to 1.0. The default ambient
* color is (0.2, 0.2, 0.2).
* - Diffuse color - the RGB color of the material when illuminated.
* The range of values is 0.0 to 1.0. The default diffuse color is
* (1.0, 1.0, 1.0).
* - Specular color - the RGB specular color of the material (highlights).
* The range of values is 0.0 to 1.0. The default specular color
* is (1.0, 1.0, 1.0).
* - Emissive color - the RGB color of the light the material emits, if
* any. The range of values is 0.0 to 1.0. The default emissive
* color is (0.0, 0.0, 0.0).
* - Shininess - the material's shininess, in the range [1.0, 128.0]
* with 1.0 being not shiny and 128.0 being very shiny. Values outside
* this range are clamped. The default value for the material's
* shininess is 64.
* - Color target - the material color target for per-vertex colors,
* one of: AMBIENT, EMISSIVE, DIFFUSE, SPECULAR, or AMBIENT_AND_DIFFUSE.
* The default target is DIFFUSE.
*
*
* The Material object also enables or disables lighting.
*/
public class Material extends NodeComponent {
/**
* For material object, specifies that Material allows reading
* individual component field information.
*/
public static final int
ALLOW_COMPONENT_READ = CapabilityBits.MATERIAL_ALLOW_COMPONENT_READ;
/**
* For material object, specifies that Material allows reading
* individual component field information.
*/
public static final int
ALLOW_COMPONENT_WRITE = CapabilityBits.MATERIAL_ALLOW_COMPONENT_WRITE;
/**
* Specifies that per-vertex colors replace the ambient material color.
* @see #setColorTarget
*
* @since Java 3D 1.3
*/
public static final int AMBIENT = 0;
/**
* Specifies that per-vertex colors replace the emissive material color.
* @see #setColorTarget
*
* @since Java 3D 1.3
*/
public static final int EMISSIVE = 1;
/**
* Specifies that per-vertex colors replace the diffuse material color.
* This is the default target.
* @see #setColorTarget
*
* @since Java 3D 1.3
*/
public static final int DIFFUSE = 2;
/**
* Specifies that per-vertex colors replace the specular material color.
* @see #setColorTarget
*
* @since Java 3D 1.3
*/
public static final int SPECULAR = 3;
/**
* Specifies that per-vertex colors replace both the ambient and the
* diffuse material color.
* @see #setColorTarget
*
* @since Java 3D 1.3
*/
public static final int AMBIENT_AND_DIFFUSE = 4;
// Array for setting default read capabilities
private static final int[] readCapabilities = {
ALLOW_COMPONENT_READ
};
/**
* Constructs and initializes a Material object using default parameters.
* The default values are as follows:
*
* lighting enable : true
* ambient color : (0.2, 0.2, 0.2)
* emmisive color : (0.0, 0.0, 0.0)
* diffuse color : (1.0, 1.0, 1.0)
* specular color : (1.0, 1.0, 1.0)
* shininess : 64
* color target : DIFFUSE
*
*/
public Material() {
// Just use the defaults
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
}
/**
* Constructs and initializes a new material object using the specified
* parameters. Lighting is enabled by default.
* @param ambientColor the material's ambient color
* @param emissiveColor the material's emissive color
* @param diffuseColor the material's diffuse color when illuminated by a
* light
* @param specularColor the material's specular color when illuminated
* to generate a highlight
* @param shininess the material's shininess in the
* range [1.0, 128.0] with 1.0 being not shiny and 128.0 being very shiny.
* Values outside this range are clamped.
*/
public Material(Color3f ambientColor,
Color3f emissiveColor,
Color3f diffuseColor,
Color3f specularColor,
float shininess) {
// set default read capabilities
setDefaultReadCapabilities(readCapabilities);
((MaterialRetained)this.retained).createMaterial(ambientColor,
emissiveColor, diffuseColor, specularColor,
shininess);
}
/**
* Creates a retained mode MaterialRetained object that this
* Material component object will point to.
*/
@Override
void createRetained() {
this.retained = new MaterialRetained();
this.retained.setSource(this);
}
/**
* Sets this material's ambient color.
* This specifies how much ambient light is reflected by
* the surface.
* The ambient color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is either AMBIENT or AMBIENT_AND_DIFFUSE, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's ambient color in the lighting equation.
*
* @param color the material's ambient color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setAmbientColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive()) {
((MaterialRetained)this.retained).setAmbientColor(color);
}
else {
((MaterialRetained)this.retained).initAmbientColor(color);
}
}
/**
* Sets this material's ambient color.
* This specifies how much ambient light is reflected by
* the surface.
* The ambient color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is either AMBIENT or AMBIENT_AND_DIFFUSE, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's ambient color in the lighting equation.
*
* @param r the new ambient color's red component
* @param g the new ambient color's green component
* @param b the new ambient color's blue component
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setAmbientColor(float r, float g, float b) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive()) {
((MaterialRetained)this.retained).setAmbientColor(r,g,b);
}
else {
((MaterialRetained)this.retained).initAmbientColor(r,g,b);
}
}
/**
* Retrieves this material's ambient color.
* @param color that will contain the material's ambient color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void getAmbientColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Material2"));
((MaterialRetained)this.retained).getAmbientColor(color);
}
/**
* Sets this material's emissive color.
* This is the color of light, if any, that the material emits.
* The emissive color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is EMISSIVE, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's emissive color in the lighting equation.
*
* @param color the new emissive color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setEmissiveColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setEmissiveColor(color);
else
((MaterialRetained)this.retained).initEmissiveColor(color);
}
/**
* Sets this material's emissive color.
* This is the color of light, if any, that the material emits.
* The emissive color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is EMISSIVE, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's emissive color in the lighting equation.
*
* @param r the new emissive color's red component
* @param g the new emissive color's green component
* @param b the new emissive color's blue component
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setEmissiveColor(float r, float g, float b) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setEmissiveColor(r,g,b);
else
((MaterialRetained)this.retained).initEmissiveColor(r,g,b);
}
/**
* Retrieves this material's emissive color and stores it in the
* argument provided.
* @param color the vector that will receive this material's emissive color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void getEmissiveColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Material2"));
((MaterialRetained)this.retained).getEmissiveColor(color);
}
/**
* Sets this material's diffuse color.
* This is the color of the material when illuminated by a light source.
* The diffuse color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is either DIFFUSE or AMBIENT_AND_DIFFUSE, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's diffuse color in the lighting equation.
*
* @param color the new diffuse color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setDiffuseColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setDiffuseColor(color);
else
((MaterialRetained)this.retained).initDiffuseColor(color);
}
/**
* Sets this material's diffuse color.
* This is the color of the material when illuminated by a light source.
* The diffuse color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is either DIFFUSE or AMBIENT_AND_DIFFUSE, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's diffuse color in the lighting equation.
*
* @param r the new diffuse color's red component
* @param g the new diffuse color's green component
* @param b the new diffuse color's blue component
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setDiffuseColor(float r, float g, float b) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setDiffuseColor(r,g,b);
else
((MaterialRetained)this.retained).initDiffuseColor(r,g,b);
}
/**
* Sets this material's diffuse color plus alpha.
* This is the color of the material when illuminated by a light source.
* The diffuse color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is either DIFFUSE or AMBIENT_AND_DIFFUSE, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's diffuse color in the lighting equation.
*
* @param r the new diffuse color's red component
* @param g the new diffuse color's green component
* @param b the new diffuse color's blue component
* @param a the alpha component used to set transparency
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setDiffuseColor(float r, float g, float b, float a) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setDiffuseColor(r,g,b,a);
else
((MaterialRetained)this.retained).initDiffuseColor(r,g,b,a);
}
/**
* Retrieves this material's diffuse color.
* @param color the vector that will receive this material's diffuse color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void getDiffuseColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Material2"));
((MaterialRetained)this.retained).getDiffuseColor(color);
}
/**
* Sets this material's specular color.
* This is the specular highlight color of the material.
* The specular color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is SPECULAR, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's specular color in the lighting equation.
*
* @param color the new specular color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setSpecularColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setSpecularColor(color);
else
((MaterialRetained)this.retained).initSpecularColor(color);
}
/**
* Sets this material's specular color.
* This is the specular highlight color of the material.
* The specular color in this Material object may be overridden by
* per-vertex colors in some cases. If vertex colors are present
* in the geometry, and lighting is enabled, and the colorTarget
* is SPECULAR, and vertex colors are
* not being ignored, then the vertex colors are used in place of
* this Material's specular color in the lighting equation.
*
* @param r the new specular color's red component
* @param g the new specular color's green component
* @param b the new specular color's blue component
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see #setColorTarget
*/
public void setSpecularColor(float r, float g, float b) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setSpecularColor(r,g,b);
else
((MaterialRetained)this.retained).initSpecularColor(r,g,b);
}
/**
* Retrieves this material's specular color.
* @param color the vector that will receive this material's specular color
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void getSpecularColor(Color3f color) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Material2"));
((MaterialRetained)this.retained).getSpecularColor(color);
}
/**
* Sets this material's shininess.
* This specifies a material specular scattering exponent, or
* shininess. It takes a floating point number in the range [1.0, 128.0]
* with 1.0 being not shiny and 128.0 being very shiny.
* Values outside this range are clamped.
* @param shininess the material's shininess
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setShininess(float shininess) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material0"));
if (isLive())
((MaterialRetained)this.retained).setShininess(shininess);
else
((MaterialRetained)this.retained).initShininess(shininess);
}
/**
* Retrieves this material's shininess.
* @return the material's shininess
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public float getShininess() {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Material2"));
return ((MaterialRetained)this.retained).getShininess();
}
/**
* Enables or disables lighting for this appearance component object.
* @param state true or false to enable or disable lighting
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public void setLightingEnable(boolean state) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material15"));
if (isLive())
((MaterialRetained)this.retained).setLightingEnable(state);
else
((MaterialRetained)this.retained).initLightingEnable(state);
}
/**
* Retrieves the state of the lighting enable flag.
* @return true if lighting is enabled, false if lighting is disabled
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*/
public boolean getLightingEnable() {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Material16"));
return ((MaterialRetained)this.retained).getLightingEnable();
}
/**
* Sets the color target for per-vertex colors. When lighting is
* enabled and per-vertex colors are present (and not ignored) in
* the geometry for a given Shape3D node, those per-vertex colors
* are used in place of the specified material color(s) for this
* Material object. The color target is ignored when lighting is
* disabled or when per-vertex colors are not used.
* The ColorInterpolator behavior also uses the color target to
* determine which color in the associated Material is modified.
* The default target is DIFFUSE.
*
* @param colorTarget one of: AMBIENT, EMISSIVE, DIFFUSE, SPECULAR, or
* AMBIENT_AND_DIFFUSE.
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @see RenderingAttributes#setIgnoreVertexColors
* @see ColorInterpolator
*
* @since Java 3D 1.3
*/
public void setColorTarget(int colorTarget) {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_WRITE))
throw new CapabilityNotSetException(J3dI18N.getString("Material3"));
if (isLive())
((MaterialRetained)this.retained).setColorTarget(colorTarget);
else
((MaterialRetained)this.retained).initColorTarget(colorTarget);
}
/**
* Retrieves the current color target for this material.
*
* @return one of: AMBIENT, EMISSIVE, DIFFUSE, SPECULAR, or
* AMBIENT_AND_DIFFUSE.
*
* @exception CapabilityNotSetException if appropriate capability is
* not set and this object is part of live or compiled scene graph
*
* @since Java 3D 1.3
*/
public int getColorTarget() {
if (isLiveOrCompiled())
if (!this.getCapability(ALLOW_COMPONENT_READ))
throw new CapabilityNotSetException(J3dI18N.getString("Material4"));
return ((MaterialRetained)this.retained).getColorTarget();
}
/**
* Returns a String representation of this Materials values.
* If the scene graph is live only those values with their
* Capability read bit set will be displayed.
*/
@Override
public String toString() {
StringBuffer str = new StringBuffer(getNamePrefix());
str.append("javax.media.j3d.Material: ");
Color3f color=new Color3f();
try {
getAmbientColor(color);
str.append("AmbientColor="+color);
} catch (CapabilityNotSetException e) {str.append("AmbientColor=N/A");}
try {
getEmissiveColor(color);
str.append(" EmissiveColor="+color);
} catch (CapabilityNotSetException ex) {str.append(" EmissiveColor=N/A");}
try {
getDiffuseColor(color);
str.append(" DiffuseColor="+color);
} catch (CapabilityNotSetException exc) {str.append(" DiffuseColor=N/A");}
try {
getSpecularColor(color);
str.append(" SpecularColor="+color);
} catch (CapabilityNotSetException exce) {str.append(" SpecularColor=N/A");}
try {
float f=getShininess();
str.append(" Shininess="+f);
} catch (CapabilityNotSetException excep) {str.append(" Shininess=N/A");}
try {
boolean b=getLightingEnable();
str.append(" LightingEnable="+b);
} catch (CapabilityNotSetException except) {str.append(" LightingEnable=N/A");}
try {
int i=getColorTarget();
str.append(" ColorTarget="+i);
} catch (CapabilityNotSetException except) {str.append(" ColorTarget=N/A");}
return new String(str);
}
/**
* @deprecated replaced with cloneNodeComponent(boolean forceDuplicate)
*/
@Override
public NodeComponent cloneNodeComponent() {
Material m = new Material();
m.duplicateNodeComponent(this);
return m;
}
/**
* Copies all node information from originalNodeComponent
into
* the current node. This method is called from the
* duplicateNode
method. This routine does
* the actual duplication of all "local data" (any data defined in
* this object).
*
* @param originalNodeComponent the original node to duplicate.
* @param forceDuplicate when set to true
, causes the
* duplicateOnCloneTree
flag to be ignored. When
* false
, the value of each node's
* duplicateOnCloneTree
variable determines whether
* NodeComponent data is duplicated or copied.
*
* @see Node#cloneTree
* @see NodeComponent#setDuplicateOnCloneTree
*/
@Override
void duplicateAttributes(NodeComponent originalNodeComponent,
boolean forceDuplicate) {
super.duplicateAttributes(originalNodeComponent,
forceDuplicate);
MaterialRetained mat = (MaterialRetained)
originalNodeComponent.retained;
MaterialRetained rt = (MaterialRetained) retained;
Color3f c = new Color3f();
mat.getAmbientColor(c);
rt.initAmbientColor(c);
mat.getEmissiveColor(c);
rt.initEmissiveColor(c);
mat.getDiffuseColor(c);
rt.initDiffuseColor(c);
mat.getSpecularColor(c);
rt.initSpecularColor(c);
rt.initShininess(mat.getShininess());
rt.initLightingEnable(mat.getLightingEnable());
rt.initColorTarget(mat.getColorTarget());
}
}