/** Company: Shout3D LLC Project: Shout3D 2.0 Sample Code Class: GradientTexture Date: July 12, 2000 Description: A subclass of PixelBasedTexture that generates a texture algorithmically. (C) Copyright Shout3D LLC. - 1997-2001 - All rights reserved */ package custom_nodes; import shout3d.core.*; import shout3d.*; import java.awt.Graphics; /** * GradientTexture * * A subclass of PixelBasedTexture that generates a texture algorithmically. * * Demonstrates how to subclass from PixelBasedTexture and use its * API to create a procedurally generated texture. * * @author Paul Isaacs */ public class GradientTexture extends PixelBasedTexture implements FieldObserver { final public IntField width = new IntField(this, "width", Field.NON_NEGATIVE_INT, 2); final public IntField height = new IntField(this, "height", Field.NON_NEGATIVE_INT, 128); final public FloatArrayField gradientColors = new FloatArrayField(this, "gradientColors", Field.COLOR_ARRAY, null ); /** * Constructs a default GradientTexture node. */ public GradientTexture() { width.addFieldObserver(this,null); height.addFieldObserver(this,null); gradientColors.addFieldObserver(this,null); } public void finalize() throws Throwable { width.removeFieldObserver(this); height.removeFieldObserver(this); gradientColors.removeFieldObserver(this); // Must call this or super classes will not properly finalize. super.finalize(); } public void onFieldChange(Field theField, Object userData) { // When the fields change, update the pixels. if (theField == width || theField == height || theField == gradientColors) updateCustomPixels(); } /** * Generates a texture that is a gradient of colors based on those * in the gradientColors field. */ public void updateCustomPixels() { if (width.getValue() <= 0 || height.getValue() <= 0 || gradientColors.getValue() == null || gradientColors.getValue().length < 3) { // fuggedaboudit. setCustomPixels(0,0,null,null,null,null); } else { // Generate the texture based on the fields. byte[][] myRed = new byte[height.getValue()][width.getValue()]; byte[][] myGreen = new byte[height.getValue()][width.getValue()]; byte[][] myBlue = new byte[height.getValue()][width.getValue()]; int numColors = gradientColors.getValue().length / 3; byte r, g, b; float rowFraction, prevAmount, nextAmount; int prevColor, nextColor; float[] gradColors = gradientColors.getValue(); // For each row of the texture for (int i = 0; i < height.getValue(); i++) { // set rowFraction to a value between 0..1 expressing how far towards maximum height this row is. rowFraction = (float)i/(float)(height.getValue()-1); // find colors before (or at) and after (or at) this row prevColor = (int) (rowFraction * (numColors-1)); nextColor = (prevColor == numColors-1) ? prevColor : prevColor + 1; // Amounts of each to mix to ramp smoothly from prevColor to nextColor prevAmount = nextColor - rowFraction*(numColors-1); nextAmount = (prevColor==nextColor) ? 1 : rowFraction*(numColors-1) - prevColor; // Mix some of each color to get the gradient color // Color values in the pixel array need to be bytes ranging 0-255 r = (byte)(255* (gradColors[3*prevColor] * prevAmount + gradColors[3*nextColor] * nextAmount)); g = (byte)(255* (gradColors[3*prevColor+1] * prevAmount + gradColors[3*nextColor+1] * nextAmount)); b = (byte)(255* (gradColors[3*prevColor+2] * prevAmount + gradColors[3*nextColor+2] * nextAmount)); // Set all pixels in the row to this color. for (int j = 0; j < width.getValue(); j++){ // Color values are bytes ranging 0-255 myRed[i][j] = r; myGreen[i][j] = g; myBlue[i][j] = b; } } // Set the pixels, alpha channel is null. setCustomPixels(width.getValue(), height.getValue(), myRed, myGreen, myBlue, null); } } }