# Metaball（元球）效果学习

Metaball的公式：

```package {
public class Metaball {
public var x:int;
public var y:int;
public var vx:Number;//x轴速度
public var vy:Number;//y轴速度

this.x=x;
this.y=y;
}

public function equation(tx:Number,ty:Number):Number {
//Metaball公式的体现：
}
}
}```

```var sW:Number=stage.stageWidth;//舞台宽度
var sH:Number=stage.stageHeight;//舞台高度
var canvas:BitmapData=new BitmapData(sW,sH,false,0xff000000);//默认生成一个黑背景的BitmapData
var rect:Rectangle=canvas.rect;//canvas的矩形区域
var pt:Point=new Point(rect.left,rect.top);//rect的左上顶点
var blurFilter:BlurFilter=new BlurFilter(10,10);//定义一个模糊滤镜
var metaballs:Array = new Array();//用于保存n个metaball的数组
var ballNumber:uint=5;//小球数目
var i:uint=0;//循环变量
var minThreshold:int=0x000009;//最小阈值
var maxThreshold:int=0x000020;//最大阈值
var bitMap:Bitmap = new Bitmap();//最终用来显示的位图对象
var isHollow:Boolean=false;//是否空心图形

function init() {
for (i=0; i<ballNumber; i++) {
var b:Metaball=new Metaball(Math.random()*sW,Math.random()*sH,20 + Math.random()*80);
} else if (b.x < b.original_radius) {
}
}
b.vx = (Math.random()*2-1)*2;
b.vy = (Math.random()*2-1)*2;
metaballs.push(b);
}
}

function enterFrameHandler(e:Event):void {
for (i=0; i<ballNumber; i++) {
var b:Metaball=metaballs[i];
b.x+=b.vx;
b.y+=b.vy;

b.vx*=-1;
b.vx*=-1;
}

b.vy*=-1;
b.vy*=-1;
}
}
canvas.dispose();
canvas = new BitmapData(sW,sH,false,0xff000000);
canvas.lock();
canvas.floodFill(0,0,0);
var sum:Number=0;
for (var ty:int = 0; ty < stage.stageHeight; ty++) {
for (var tx:int = 0; tx < stage.stageWidth; tx++) {
sum=0;
for (var i:int = 0; i < metaballs.length; i++) {
sum+=metaballs[i].equation(tx,ty);
}

if (! isHollow) {
if (sum>=minThreshold) {
canvas.setPixel(tx, ty, 0xFFFFFF);
}
} else {
if (sum>=minThreshold&&sum<=maxThreshold) {
canvas.setPixel(tx, ty, 0xFFFFFF);
}
}
}
}
canvas.applyFilter(canvas,rect,pt,blurFilter);
canvas.unlock();
bitMap.bitmapData=canvas;
}

init();```

```<languageVersion : 1.0;>

kernel Metaballs
<   namespace : "com.rocketmandevelopment";
vendor : "Rocketman Development";
version : 1;
description : "Fast Metaballs";
>
{
parameter float minThreshold
<
minValue:float(0.0);
maxValue:float(2.0);
defaultValue:float(0.9);
description: "minThreshold";
>;
//no max threshold because I want these balls completely filled
parameter float3 ball1
<//this is where it gets odd. Pixel bender with flash doesn't support loops, so you must pass in each ball individually. This limits the amount of balls to the amount defined in the filter
minValue:float3(0.0,0.0,0.0); //storing the data is also odd. We'll use a float3, which is like an array of 3 float values.
maxValue:float3(640.0,480.0,50.0); //this first is the x, second is y, and the third is radius.
defaultValue:float3(50.0,50.0,20.0);
>;

parameter float3 ball2
<
minValue:float3(0.0,0.0,0.0);
maxValue:float3(640.0,480.0,50.0);//this example only supports two balls
defaultValue:float3(100.0,100.0,20.0);
>;

input image4 src;
output pixel4 dst;

void
evaluatePixel()
{
dst = sampleNearest(src,outCoord());
dst.rbg = float3(0,0,0);//sets the current pixel to black so the image is cleared before redrawing
float2 coord = outCoord(); //get the coordinate of the pixel
float sum = 0.0; //get the sum and set it to 0
sum += (ball1.z)/((ball1.x-coord.x)*(ball1.x-coord.x)+(ball1.y-coord.y)*(ball1.y-coord.y)); //add to the sum using the formula from the first example
sum += (ball2.z)/((ball2.x-coord.x)*(ball2.x-coord.x)+(ball2.y-coord.y)*(ball2.y-coord.y));
if(sum >= minThreshold){
dst.rgb = float3(255,255,255); //set it to black if its within the threshold
}

}
}```

```package {
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.utils.ByteArray;
import flash.display.Bitmap;
import flash.display.BitmapData;

[SWF(height=300,width=300)]
public class PixelBenderMetaballs extends Sprite {
[Embed(source='metaball.pbj',mimeType='application/octet-stream')]
private static const MetaballsFilter:Class;

private const canvas:BitmapData=new BitmapData(300,300,false,0);
private const blur:BlurFilter=new BlurFilter(10,10,1);
private var b1:Metaball;
private var b2:Metaball;
private var b:Bitmap;

public function PixelBenderMetaballs() {
b=new Bitmap(canvas);
b.smoothing=true;

var ba:ByteArray = new MetaballsFilter() as ByteArray;

b1=new Metaball(100,100,Math.random()*20 + 30);
b2=new Metaball(150,150,Math.random()*20 + 30);

b1.vx = (Math.random()*2-1)*5;
b1.vy = (Math.random()*2-1)*5;
b2.vx = (Math.random()*2-1)*5;
b2.vy = (Math.random()*2-1)*5;

b.filters=[metaballsFilter];
}

private function enterFrameHandler(e:Event):void {
b1.x+=b1.vx;
b1.y+=b1.vy;
checkWalls(b1);

b2.x += b2.vx;
b2.y += b2.vy;
checkWalls(b2);

b.filters=[metaballsFilter,blur];
}

private function checkWalls(ball:Metaball):void {
var sw:Number=stage.stageWidth;
var sh:Number=stage.stageHeight;
ball.vx*=-1;
ball.vx*=-1;
}
ball.vy*=-1;
ball.vy*=-1;
}
}

}
}```

```var ballNum:uint=5;
var balls:Array = new Array();
var sW:Number=stage.stageWidth;
var sH:Number=stage.stageHeight;
var container:Sprite = new Sprite();
var bmd:BitmapData=new BitmapData(sW,sH,false,0x00000000);
var bitmap:Bitmap;
var i:uint=0;
var rect:Rectangle=new Rectangle(0,0,sW,sH);
var pt:Point=new Point(0,0);
var filter:BlurFilter=new BlurFilter(10,10);

function init() {
for (i=0; i<ballNum; i++) {
var b:Ball=new Ball(15+Math.random()*20,0xffffff);
balls.push(b);
b.x = (sW - b.width)*Math.random() + b.radius;
b.y = (sH - b.width)*Math.random() + b.radius;
b.vx=(Math.random()*2-1)*1;
b.vy=(Math.random()*2-1)*1;
}

bmd.draw(container);
bmd.applyFilter(bmd, rect, pt, filter);
bitmap=new Bitmap(bmd);
}

function enterFrameHandler(e:Event):void {
for (i=0; i<ballNum; i++) {
var b:Ball=balls[i];
b.x+=b.vx;
b.y+=b.vy;
b.vx*=-1;
b.vx*=-1;
}

b.vy*=-1;
b.vy*=-1;
}
}

bmd.dispose();
bmd=new BitmapData(sW,sH,false,0x00000000);
bmd.draw(container);
bmd.applyFilter(bmd, rect, pt, filter);
bitmap.bitmapData=bmd;
}

init();```

1025 篇文章76 人订阅

0 条评论

## 相关文章

11220

10820

281100

### 浅扒Android动态设置字体大小

Android开发中,TextView类的控件应该说是很常用了。一般来说我们是通过android:textSize="20sp" 来设置字体大小，但是很多时候...

15730

21730

11520

### （数据科学学习手札42）folium进阶内容介绍

在上一篇（数据科学学习手札41）中我们了解了folium的基础内容，实际上folium在地理信息可视化上的真正过人之处在于其绘制图像的高度可定制化上，本文就...

32840

14820

12340

51980