All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.media.j3d.ColorInterpolator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 1997-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 java.util.Enumeration;

import javax.vecmath.Color3f;

/**
 * Color interpolation behavior.  This class defines a behavior that
 * modifies the ambient, emissive, diffuse, or specular color of its
 * target material object by linearly interpolating between a pair of
 * specified colors, using the value generated by the specified Alpha
 * object.
 * The behavior modifies the color specified by the
 * Material's colorTarget attribute, one of: AMBIENT, EMISSIVE,
 * DIFFUSE, SPECULAR, or AMBIENT_AND_DIFFUSE.
 * The ALLOW_COMPONENT_READ bit must be set in the  Material object in
 * order for the Material's colorTarget to be read.
 * If the Material object's ALLOW_COMPONENT_READ bit is not set, the
 * diffuse component will be modified.
 *
 * @see Material
 */

public class ColorInterpolator extends Interpolator {

    Material target;
    Color3f startColor = new Color3f();
    Color3f endColor = new Color3f();
    Color3f newColor = new Color3f();

    // We can't use a boolean flag since it is possible
    // that after alpha change, this procedure only run
    // once at alpha.finish(). So the best way is to
    // detect alpha value change.
    private float prevAlphaValue = Float.NaN;
    private int prevColorTarget = -1;
    private WakeupCriterion passiveWakeupCriterion = new WakeupOnElapsedFrames(0, true);

    // non-public, no parameter constructor used by cloneNode
    ColorInterpolator() {
    }

    /**
     * Constructs a trivial color interpolator with a specified target,
     * a starting color of black, and an ending color of white.
     * @param alpha the alpha object for this interpolator
     * @param target the material component object whose
     * color is affected by this color interpolator
     */
    public ColorInterpolator(Alpha alpha,
			     Material target) {

	super(alpha);

	this.target = target;
	this.startColor.set(0.0f, 0.0f, 0.0f);
	this.endColor.set(1.0f, 1.0f, 1.0f);
    }

    /**
     * Constructs a color interpolator with the specified target,
     * starting color, and ending color.
     * @param alpha the alpha object for this interpolator
     * @param target the material component object whose
     * color is affected by this color interpolator
     * @param startColor the starting color
     * @param endColor the ending color
     */
    public ColorInterpolator(Alpha alpha,
			     Material target,
			     Color3f startColor,
			     Color3f endColor) {

	super(alpha);

	this.target = target;
	this.startColor.set(startColor);
	this.endColor.set(endColor);
    }

    /**
      * This method sets the startColor for this interpolator.
      * @param color the new start color
      */
    public void setStartColor(Color3f color) {
	startColor.set(color);
	prevAlphaValue = Float.NaN;
    }

    /**
      * This method retrieves this interpolator's startColor.
      * @param color the vector that will receive the interpolator's start color
      */
    public void getStartColor(Color3f color) {
	color.set(startColor);
    }

    /**
      * This method sets the endColor for this interpolator.
      * @param color the new end color
      */
    public void setEndColor(Color3f color) {
	endColor.set(color);
	prevAlphaValue = Float.NaN;
    }

    /**
      * This method retrieves this interpolator's endColor.
      * @param color the vector that will receive the interpolator's end color
      */
    public void getEndColor(Color3f color) {
	color.set(endColor);
    }

    /**
     * This method sets the target material component object for
     * this interpolator.
     * @param target the material component object whose
     * color is affected by this color interpolator
     */
    public void setTarget(Material target) {
	this.target = target;
	prevAlphaValue = Float.NaN;
    }

    /**
      * This method retrieves this interpolator's target material
      * component object.
      * @return the interpolator's target material component object
      */
    public Material getTarget() {
	return target;
    }

    // The ColorInterpolator's initialize routine uses the default
    // initialization routine.

    /**
     * This method is invoked by the behavior scheduler every frame.
     * It maps the alpha value that corresponds to the current time
     * into a color value and updates the ambient, emissive, diffuse,
     * or specular color (or both the ambient and diffuse color) of
     * the specified target Material object with this new color value.
     *
     * @param criteria an enumeration of the criteria that caused the
     * stimulus
     */
    @Override
    public void processStimulus(Enumeration criteria) {

	// Handle stimulus
	WakeupCriterion criterion = passiveWakeupCriterion;

	if (alpha != null) {
	    float value = alpha.value();

	    int colorTarget = Material.DIFFUSE;
	    if (target.getCapability(Material.ALLOW_COMPONENT_READ))
		colorTarget = target.getColorTarget();

	    if (value != prevAlphaValue || colorTarget != prevColorTarget) {
		newColor.x = (1.0f-value)*startColor.x + value*endColor.x;
		newColor.y = (1.0f-value)*startColor.y + value*endColor.y;
		newColor.z = (1.0f-value)*startColor.z + value*endColor.z;

		switch (colorTarget) {
		case Material.AMBIENT:
		    target.setAmbientColor(newColor);
		    break;
		case Material.AMBIENT_AND_DIFFUSE:
		    target.setAmbientColor(newColor);
		    // fall through
		case Material.DIFFUSE:
		    target.setDiffuseColor(newColor);
		    break;
		case Material.EMISSIVE:
		    target.setEmissiveColor(newColor);
		    break;
		case Material.SPECULAR:
		    target.setSpecularColor(newColor);
		    break;
		}

		prevAlphaValue = value;
		prevColorTarget = colorTarget;
	    }

	    if (!alpha.finished() && !alpha.isPaused()) {
		criterion = defaultWakeupCriterion;
	    }
	}
	wakeupOn(criterion);
    }

    /**
     * Used to create a new instance of the node.  This routine is called
     * by cloneTree to duplicate the current node.
     * @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 Node#cloneNode
     * @see Node#duplicateNode
     * @see NodeComponent#setDuplicateOnCloneTree
     */
    @Override
    public Node cloneNode(boolean forceDuplicate) {
        ColorInterpolator ci = new ColorInterpolator();
        ci.duplicateNode(this, forceDuplicate);
        return ci;
    }


   /**
     * Copies all ColorInterpolator information from
     * originalNode into
     * the current node.  This method is called from the
     * cloneNode method which is, in turn, called by the
     * cloneTree method.

* * @param originalNode 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. * * @exception RestrictedAccessException if this object is part of a live * or compiled scenegraph. * * @see Node#duplicateNode * @see Node#cloneTree * @see NodeComponent#setDuplicateOnCloneTree */ @Override void duplicateAttributes(Node originalNode, boolean forceDuplicate) { super.duplicateAttributes(originalNode, forceDuplicate); ColorInterpolator ci = (ColorInterpolator) originalNode; ci.getStartColor(startColor); ci.getEndColor(endColor); // this reference will be updated in updateNodeReferences() setTarget(ci.getTarget()); } /** * Callback used to allow a node to check if any scene graph objects * referenced * by that node have been duplicated via a call to cloneTree. * This method is called by cloneTree after all nodes in * the sub-graph have been duplicated. The cloned Leaf node's method * will be called and the Leaf node can then look up any object references * by using the getNewObjectReference method found in the * NodeReferenceTable object. If a match is found, a * reference to the corresponding object in the newly cloned sub-graph * is returned. If no corresponding reference is found, either a * DanglingReferenceException is thrown or a reference to the original * object is returned depending on the value of the * allowDanglingReferences parameter passed in the * cloneTree call. *

* NOTE: Applications should not call this method directly. * It should only be called by the cloneTree method. * * @param referenceTable a NodeReferenceTableObject that contains the * getNewObjectReference method needed to search for * new object instances. * @see NodeReferenceTable * @see Node#cloneTree * @see DanglingReferenceException */ @Override public void updateNodeReferences(NodeReferenceTable referenceTable) { super.updateNodeReferences(referenceTable); // check Material NodeComponent nc = getTarget(); if (nc != null) { setTarget((Material) referenceTable.getNewObjectReference(nc)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy