Fur
@see http://b-o-w.jp/blog/2008/12/14/fluffy_fur_rendering/
* テクスチャ一色にして毛がなびくの少なくしてみた
/**
* @see http://b-o-w.jp/blog/2008/12/14/fluffy_fur_rendering/
* テクスチャ一色にして毛がなびくの少なくしてみた
*/
package {
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.TriangleCulling;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Utils3D;
import flash.geom.Vector3D;
import flash.utils.getTimer;
[SWF(width=465,height=465,frameRate=60,backgroundColor=0xFFFFFF)]
public class Fur extends Sprite {
private const FUR_DEPTH:uint = 10;
private var vertices:Vector.<Number> = new Vector.<Number>(0, false);
private var projected:Vector.<Number> = new Vector.<Number>(0, false);
private var indices:Vector.<int> = new Vector.<int>(0, false);
private var uvtData:Vector.<Number> = new Vector.<Number>(0, false);
private var projection:PerspectiveProjection = new PerspectiveProjection();
private var textures:Array = [];
private var view:Matrix3D = new Matrix3D();
public function Fur() {
x = y = 465 / 2;
createGeometry(10, 6);
projection.fieldOfView = 60;
textures.push(new BitmapData(512, 512, false, 0xCCAA66));
for (var i:uint=1; i<FUR_DEPTH; i++) {
textures.push(new Texture(i / FUR_DEPTH * 1.2 + 0.5, 1 - i / FUR_DEPTH));
}
addEventListener(Event.ENTER_FRAME, enterFrame);
}
private function createGeometry(xDiv:uint, yDiv:uint):void {
for (var y:uint=0; y<=yDiv; y++) {
var yr:Number = y / yDiv;
var cy:Number = Math.cos(yr * Math.PI);
var sy:Number = Math.sin(yr * Math.PI);
for (var x:uint=0; x<=xDiv; x++) {
var xr:Number = x / xDiv;
var cx:Number = Math.cos(xr * Math.PI * 2);
var sx:Number = Math.sin(xr * Math.PI * 2);
vertices.push(cx * sy, cy, sx * sy);
uvtData.push(xr, yr, 0);
if (y < yDiv) {
var i1:uint = y * (xDiv + 1) + x;
var i2:uint = y * (xDiv + 1) + ((x + 1) % (xDiv + 1));
var i3:uint = (y + 1) * (xDiv + 1) + x;
var i4:uint = (y + 1) * (xDiv + 1) + ((x + 1) % (xDiv + 1));
indices.push(i1, i2, i3, i3, i2, i4);
}
}
}
}
private function enterFrame(event:Event):void {
var count:Number = getTimer() / 1000 * 60;
graphics.clear();
for (var i:uint=0; i<FUR_DEPTH; i++) {
var scale:Number = 200 + i * 7;
view.identity();
view.appendScale(scale, scale, scale);
view.appendRotation(Math.cos(count * 0.0045) * 120, Vector3D.X_AXIS);
view.appendRotation(Math.cos(count * 0.0081) * 120, Vector3D.Y_AXIS);
view.appendTranslation(0, 0, 850);
view.append(projection.toMatrix3D());
Utils3D.projectVectors(view, vertices, projected, uvtData);
graphics.beginBitmapFill(textures[i], null, false, true);
graphics.drawTriangles(projected, indices, uvtData, TriangleCulling.POSITIVE);
count -= 1.5;
}
}
}
}
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.geom.ColorTransform;
class Texture extends BitmapData {
private static var noiseBitmap:BitmapData = createNoiseBitmap();
private static function createNoiseBitmap():BitmapData {
var noiseBitmap:BitmapData = new BitmapData(512, 512, false);
noiseBitmap.noise(0, 0, 255, BitmapDataChannel.BLUE, false);
var palette:Array = [];
for (var i:uint=0; i<256; i++) {
palette[i] = Math.max(0, Math.pow(i / 0xFF * 1.7 - 0.7, 0.1) * 0xFF);
}
noiseBitmap.paletteMap(noiseBitmap, noiseBitmap.rect, noiseBitmap.rect.topLeft, null, null, palette);
return noiseBitmap;
}
public function Texture(colorMultiplier:Number, alphaMultiplier:Number) {
super(512, 512, true, 0xFF009900);
//perlinNoise(64, 64, 1, 0, true, true);
copyChannel(noiseBitmap, rect, rect.topLeft, BitmapDataChannel.BLUE, BitmapDataChannel.ALPHA);
colorTransform(rect, new ColorTransform(colorMultiplier, colorMultiplier, colorMultiplier, alphaMultiplier));
}
}