javax.media.j3d.Material.java Source code

Java tutorial

Introduction

Here is the source code for javax.media.j3d.Material.java

Source

/*
 * 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 <code>null</code>,
 * lighting is disabled for all nodes that use that Appearance object.
 * <P>
 * The properties that can be set for a Material object are:
 * <P><UL>
 * <LI>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).<p></LI>
 * <LI>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).<p></LI>
 * <LI>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).<p></LI>
 * <LI>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).<p></LI>
 * <LI>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.<p></LI>
 * <LI>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.<p></LI>
 * </UL>
 *
 * 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:
     * <ul>
     * lighting enable : true<br>
     * ambient color : (0.2, 0.2, 0.2)<br>
     * emmisive color : (0.0, 0.0, 0.0)<br>
     * diffuse color : (1.0, 1.0, 1.0)<br>
     * specular color : (1.0, 1.0, 1.0)<br>
     * shininess : 64<br>
     * color target : DIFFUSE
     * </ul>
     */
    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 <code>originalNodeComponent</code> into
     * the current node.  This method is called from the
     * <code>duplicateNode</code> 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 <code>true</code>, causes the
     *  <code>duplicateOnCloneTree</code> flag to be ignored.  When
     *  <code>false</code>, the value of each node's
     *  <code>duplicateOnCloneTree</code> 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());
    }

}