Hello,

  I don't know if this has been fixed recently, but in the Elevation
class, generate() method, there is a "break" missing in the switch
statement, for color channel "b".

Also, in the "av" channel equation, I am not sure if this is correct:

cha = ((color >> 16 & 0xFF)*0.212671) + ((color >> 8 & 0xFF)*0.715160)
+ ((color >> 8 & 0xFF)*0.072169);

I think it the blue channel portion should be:

cha = ((color >> 16 & 0xFF)*0.212671) + ((color >> 8 & 0xFF)*0.715160)
+ ((color >> 0xFF)*0.072169);

(Or is that even the blue channel?)

Finally, I would like to submit my re-working of this class for some
minor speed improvements.  I have added a generateAverage() method,
since that is the odd one, and removed the switch and inline-if from
inside the for-loop.  Also, I have set up the channel bit references
and multipliers as private static const's.  These might be moved to a
public static const in a base class, and used elsewhere as needed,
too.

Entire Elevation class follows:

==============

package away3d.extrusions
{
        import flash.display.BitmapData;
        import away3d.core.math.Number3D;

        /**
        * Class Elevation returns a multidimentional array of Number3D's to
pass to the SkinClass in order to generate an elevated mesh from
<Elevation></code>
        *
        */
        public class Elevation {

                private var _minElevation:Number = 0;
                private var _maxElevation:Number = 255;

                /**
                * Locks elevation factor beneath this level. Default is 0;
                *
                */
                public function set minElevation(val:Number):void
        {
                        _minElevation = val;
                }
                public function get minElevation():Number
        {
                        return _minElevation;
                }
                /**
                * Locks elevation factor above this level. Default is 255;
                *
                */
                public function set maxElevation(val:Number):void
        {
                        _maxElevation = val;
                }
                public function get maxElevation():Number
        {
                        return _maxElevation;
                }

                /**
                * Creates a generate <code>Elevation</code> object.
                *
                 */
                public function Elevation()
        {
                }

                /**
                * Generate the Array representing the mesh
                *
                * @param        sourceBmd                               
Bitmapdata. The bitmapData to read from.
                * @param        channel                                 
[optional] String. The channel information to
read. supported "a", alpha, "r", red, "g", green, "b", blue and
"av" (averages and luminance). Default is red channel "r".
                * @param        subdivisionX                    [optional] int. 
The subdivision to read the
pixels along the x axis. Default is 10.
                * @param        subdivisionY                    [optional] int. 
The subdivision to read the
pixels along the y axis. Default is 10.
                * @param        scalingX                                        
[optional] Number. The scale multiplier along
the x axis. Default is 1.
                * @param        scalingY                                        
[optional] Number. The scale multiplier along
the y axis. Default is 1.
                * @param        elevate                                 
[optional] Number. The scale multiplier along
the z axis. Default is .5.
                */

                public function generate(sourceBmd:BitmapData, channel:String = 
"r",
subdivisionX:int = 10, subdivisionY:int = 10, scalingX:Number = 1,
scalingY:Number = 1, elevate:Number = .5):Array
                {
                        channel = channel.toLowerCase();

                        var w:int = sourceBmd.width;
                        var h:int = sourceBmd.height;
                        var i:int;
                        var j:int;
                        var x:Number = 0;
                        var y:Number = 0;
                        var z:Number = 0;
                        var totalArray:Array = [];
                        var tmpArray:Array = [];
                        var color:uint;
                        var cha:Number;


                        for(j = h-1; j >-subdivisionY; j-=subdivisionY)
                        {
                                y = (j<0)? 0 : j;
                                tmpArray = [];

                                for(i = 0; i < w+subdivisionX; i+=subdivisionX)
                                {
                                        x = (i<w-1)? i : w-1;

                                        color = (channel == "a")? 
sourceBmd.getPixel32(x, y) :
sourceBmd.getPixel(x, y);

                                        switch(channel){
                                                case "a":
                                                        cha = color >> 24 & 
0xFF;
                                                        break;
                                                case "r":
                                                        cha = color >> 16 & 
0xFF;
                                                        break;
                                                case "g":
                                                        cha = color >> 8 & 0xFF;
                                                        break;
                                                case "b":
                                                        cha = color & 0xFF;
                                                case "av":
                                                        cha = ((color >> 16 & 
0xFF)*0.212671) + ((color >> 8 & 0xFF)
*0.715160) + ((color >> 8 & 0xFF)*0.072169);
                                        }

                                        if(maxElevation < cha)
                                                cha = maxElevation;

                                        if(minElevation > cha)
                                                cha = minElevation;

                                        z = cha*elevate;

                                        tmpArray.push(new Number3D(x*scalingX, 
y*scalingY, z));
                                }

                                totalArray.push(tmpArray);
                        }

                        return totalArray;
                }

                // NEW GENERATE FUNCTIONS:

                private static const ALPHA_CHANNEL:int = 24 & 0xFF;
                private static const RED_CHANNEL:int = 16 & 0xFF;
                private static const GREEN_CHANNEL:int = 8 & 0xFF;
                private static const BLUE_CHANNEL:int = 0xFF;

                private static const RED_AVG:Number = 0.212671;
                private static const BLUE_AVG:Number = 0.715160;
                private static const GREEN_AVG:Number = 0.072169;

                /**
                * generate_new
                *
                * Delfeld, 2009
                *
                * Generate the Array representing the mesh for RGBA (but not
average) color channel; serves as a passthrough method for
generateAverage.
                *
                * @param        sourceBmd                               
Bitmapdata. The bitmapData to read from.
                * @param        channel                                 
[optional] String. The channel information to
read. supported "a", alpha, "r", red, "g", green, "b", blue and
"av" (averages and luminance). Default is red channel "r".
                * @param        subdivisionX                    [optional] int. 
The subdivision to read the
pixels along the x axis. Default is 10.
                * @param        subdivisionY                    [optional] int. 
The subdivision to read the
pixels along the y axis. Default is 10.
                * @param        scalingX                                        
[optional] Number. The scale multiplier along
the x axis. Default is 1.
                * @param        scalingY                                        
[optional] Number. The scale multiplier along
the y axis. Default is 1.
                * @param        elevate                                 
[optional] Number. The scale multiplier along
the z axis. Default is .5.
                */

                public function generate_new(sourceBmd:BitmapData, 
channel:String =
"r", subdivisionX:int = 10, subdivisionY:int = 10, scalingX:Number =
1, scalingY:Number = 1, elevate:Number = .5):Array
                {
                        channel = channel.toLowerCase();

                        if ( channel == "av" )
                        {
                                return generateAverage(sourceBmd, channel, 
subdivisionX,
subdivisionY, scalingX, scalingY, elevate);
                        }

                        trace("Elevation.generate_new");

                        var w:int = sourceBmd.width;
                        var h:int = sourceBmd.height;
                        var i:int;
                        var j:int;
                        var x:Number = 0;
                        var y:Number = 0;
                        var z:Number = 0;
                        var totalArray:Array = [];
                        var tmpArray:Array = [];
                        //var color:uint;
                        var cha:Number;

                        var bit:int;
                        switch(channel){
                                case "a":
                                        bit = ALPHA_CHANNEL;
                                        break;
                                case "r":
                                        bit = RED_CHANNEL;
                                        break;
                                case "g":
                                        bit = GREEN_CHANNEL;
                                        break;
                                case "b":
                                        bit = BLUE_CHANNEL;
                                        break;
                                default:
                                        throw new 
Error("Elevation.generate_new: Invalid channel: " +
channel + "\n");
                                        return null;
                        }

                        var getColorFunction:Function = (channel == "a")?
sourceBmd.getPixel32 : sourceBmd.getPixel;

                        for(j = h-1; j >-subdivisionY; j-=subdivisionY)
                        {
                                y = (j<0)? 0 : j;
                                tmpArray = [];

                                for(i = 0; i < w+subdivisionX; i+=subdivisionX)
                                {
                                        x = (i<w-1)? i : w-1;

                                        //color = (channel == "a")? 
sourceBmd.getPixel32(x, y) :
sourceBmd.getPixel(x, y);

                                        cha = getColorFunction(x, y) >> bit;

                                        //switch(channel){
                                                //case "a":
                                                        //cha = color >> 24 & 
0xFF;
                                                        //break;
                                                //case "r":
                                                        //cha = color >> bit & 
0xFF;
                                                        //break;
                                                //case "g":
                                                        //cha = color >> 8 & 
0xFF;
                                                        //break;
                                                //case "b":
                                                        //cha = color & 0xFF;
                                                //case "av":
                                                        //cha = ((color >> 16 & 
0xFF)*0.212671) + ((color >> 8 & 0xFF)
*0.715160) + ((color >> 8 & 0xFF)*0.072169);
                                        //}

                                        if(maxElevation < cha)
                                                cha = maxElevation;

                                        if(minElevation > cha)
                                                cha = minElevation;

                                        z = cha*elevate;

                                        tmpArray.push(new Number3D(x*scalingX, 
y*scalingY, z));
                                }

                                totalArray.push(tmpArray);
                        }

                        return totalArray;
                }

                /**
                * generateAverage
                *
                * Delfeld, 2009
                *
                * Generate the Array representing the mesh for the average color
channels.
                *
                * @param        sourceBmd                               
Bitmapdata. The bitmapData to read from.
                * @param        channel                                 
[optional] String. The channel information to
read. supported "a", alpha, "r", red, "g", green, "b", blue and
"av" (averages and luminance). Default is red channel "r".
                * @param        subdivisionX                    [optional] int. 
The subdivision to read the
pixels along the x axis. Default is 10.
                * @param        subdivisionY                    [optional] int. 
The subdivision to read the
pixels along the y axis. Default is 10.
                * @param        scalingX                                        
[optional] Number. The scale multiplier along
the x axis. Default is 1.
                * @param        scalingY                                        
[optional] Number. The scale multiplier along
the y axis. Default is 1.
                * @param        elevate                                 
[optional] Number. The scale multiplier along
the z axis. Default is .5.
                */

                public function generateAverage(sourceBmd:BitmapData, 
channel:String
= "av", subdivisionX:int = 10, subdivisionY:int = 10, scalingX:Number
= 1, scalingY:Number = 1, elevate:Number = .5):Array
                {
                        channel = channel.toLowerCase();

                        if ( channel != "av" )
                        {
                                return generate_new(sourceBmd, channel, 
subdivisionX,
subdivisionY, scalingX, scalingY, elevate);
                        }

                        trace("Elevation.generateAverage");

                        var w:int = sourceBmd.width;
                        var h:int = sourceBmd.height;
                        var i:int;
                        var j:int;
                        var x:Number = 0;
                        var y:Number = 0;
                        var z:Number = 0;
                        var totalArray:Array = [];
                        var tmpArray:Array = [];
                        var color:uint;
                        var cha:Number;

                        for(j = h-1; j >-subdivisionY; j-=subdivisionY)
                        {
                                y = (j<0)? 0 : j;
                                tmpArray = [];

                                for(i = 0; i < w+subdivisionX; i+=subdivisionX)
                                {
                                        x = (i<w-1)? i : w-1;

                                        color = sourceBmd.getPixel(x, y);
                                        cha =
                                                ((color >> RED_CHANNEL) * 
RED_AVG)
                                                + ((color >> GREEN_CHANNEL) * 
GREEN_AVG)
                                                + ((color >> BLUE_CHANNEL) * 
BLUE_AVG)
                                        ;

                                        if(maxElevation < cha)
                                                cha = maxElevation;

                                        if(minElevation > cha)
                                                cha = minElevation;

                                        z = cha*elevate;

                                        tmpArray.push(new Number3D(x*scalingX, 
y*scalingY, z));
                                }

                                totalArray.push(tmpArray);
                        }

                        return totalArray;
                }
        }
}

Reply via email to