java有没有噪声函数_Java Chaos Game噪声游戏实例代码

[简介]

最近一直在读《深奥的简洁》,里面有一章介绍了几种使用噪声产生分形图的方法,感觉很有意思,于是尝试使用计算机模拟了一下,效果还不错(噪声法比传统迭代法在编程上好实现一些,后来发现这类算法还不少,搜索chaosgame可以找到更多)。

[Sierpinski三角形的噪声产生法]

a16fbdca6edc4cc0ab47f44883be32cd.png

在这些噪声游戏中,Sierpinski(谢尔宾斯基)三角形的生成规则可谓是最简单的:

1.在平面上选取三个点,标记为1、2、3,作为大三角形的顶点。

2.选择其中一点,作为“当前点”(比如选择1号)。

3.产生1~3的随机数,在该数表达的顶点与“当前点”的中点绘制一个新点,并将新点作为“当前点”。

4.重复步骤3,即可逼近图案。

*.注意随机数最好不要使用以时间作为种子的产生方式。

[模拟程序]

package com.geiv.chaos;

import java.awt.event.KeyEvent;

import com.thrblock.util.RandomSet;

import geivcore.DefaultFactor;

import geivcore.KeyFactor;

import geivcore.KeyListener;

import geivcore.R;

import geivcore.UESI;

import geivcore.enginedata.obj.Obj;

public class Sierpinski extends DefaultFactor implements KeyListener{

UESI UES;

Obj[] basePoint;

Obj crtPoint;

public Sierpinski(UESI UES,int times){

this.UES = UES;

basePoint = new Obj[3];

//创建三个基准点

for (int i = 0;i < 3;i++){

basePoint[i] = UES.creatObj(UESI.BGIndex);

basePoint[i].addGLPoint("70DBDB",0,0);

basePoint[i].show();

}

basePoint[0].setCentralX(400);

//设置三点位置

basePoint[0].setCentralY(60);

basePoint[1].setCentralX(60);

basePoint[1].setCentralY(550);

basePoint[2].setCentralX(740);

basePoint[2].setCentralY(550);

crtPoint = basePoint[0];

//将0号点作为当前点

this.setKeyListener(this);

UES.pushKeyBoardIO(this);

for (int i = 0;i < times;i++){

generateNew();

}

}

@Override

public void doKeyBord(KeyFactor whom, int keyCode, Boolean ispressed) {

//挂载回调

if(ispressed){

if(keyCode == KeyEvent.VK_SPACE){

//空格对应创建一个新点

generateNew();

} else if(keyCode == KeyEvent.VK_A){

//A对应创建100个新点

for (int i = 0;i < 100;i++){

generateNew();

}

} else if(keyCode == KeyEvent.VK_B){

//B对应创建1000个新点

for (int i = 0;i < 1000;i++){

generateNew();

}

}

}

}

public void generateNew(){

Obj flagPoint = basePoint[RandomSet.getRandomNum(0, 2)];

//随机选择基准点之一

float nx = (flagPoint.getCentralX() + crtPoint.getCentralX())/2f;

//计算中点

float ny = (flagPoint.getCentralY() + crtPoint.getCentralY())/2f;

Obj newPoint = UES.creatObj(UESI.BGIndex);

//创建新点

newPoint.addGLPoint("70DBDB",0,0);

newPoint.setColor(RandomSet.getRandomColdColor());

newPoint.setCentralX(nx);

//设置坐标

newPoint.setCentralY(ny);

newPoint.show();

crtPoint = newPoint;

//置为当前点

}

public static void main(String[] args) {

UESI ues = new R();

new Sierpinski(ues,0);

//后面的构造参数可以设置初始点数。

}

}

[模拟结果]

在B键按下时

3bcfcd71356af77212aead24ca70f9db.png

f4bbfbfc51eecd7405f104fb1f84a76f.png

0cc754d95f5cc0d13117b21f61d76965.png

[Barnsleyfern的噪声产生法]

1a88747850f81be265c39a42ce5602d5.png

相比于Sierpinski三角的简单规则性,Barnsleyfern(分形羊齿草)给人以更加复杂的印象,出于它的复杂性,混沌学科经常拿出它来证明“简单规则也可产生复杂对象”的结论。

它的产生规则也不是很复杂:

1.首先给定”当前点”(0,0),我们用ox,oy表示横纵坐标。

2.计算下一点(nx,ny)需要以一定随机规则选择下列四种迭代公式之一:

1)以%1的概率选择此迭代公式:

nx=0;

ny=0.16f*oy;

2)以%85的概率选择此迭代公式:

nx=0.85*ox+0.04*oy;

ny=-0.04*ox+0.85*oy+1.6;

3)以%7的概率选择此迭代公式:

nx=0.2*ox-0.26*oy;

ny=0.23*ox+0.22*oy+1.6;

4)以%7的概率选择此迭代公式:

nx=-0.15*ox+0.28*oy;

ny=0.26*ox+0.24*oy+0.44;

3.绘制(nx,ny),并将其设为当前点,重复2,即可无限逼近结果。

↑以上公式摘自Wiki:http://en.wikipedia.org/wiki/Barnsley_fern。在编程时,我发现一个问题,Wiki并未指明这个坐标的决对值与屏幕大小的关系,也并未说明x、y轴的方向,在我自己定义的坐标系下绘制总是不成功,后来我按照公式搜索,找到了这个面:http://people.sc.fsu.edu/~jburkardt/cpp_src/fern_opengl/fern.cpp。这是一个C++下的OPENGL程序,而里面用了与Wiki相同的公式,也就是说,这组公式是以Opengl的坐标系为基准的,在做了对应变换后终于成功绘制。

[模拟程序]

package com.geiv.chaos;

import geivcore.DefaultFactor;

import geivcore.KeyFactor;

import geivcore.KeyListener;

import geivcore.R;

import geivcore.UESI;

import geivcore.enginedata.obj.Obj;

import java.awt.Color;

import java.awt.event.KeyEvent;

import com.thrblock.util.RandomSet;

public class Barnsleyfern extends DefaultFactor implements KeyListener{

UESI UES;

Obj crtPoint;

public Barnsleyfern(UESI UES,int times){

this.UES = UES;

crtPoint = UES.creatObj(UESI.BGIndex);

crtPoint.addGLPoint("70DBDB",0,0);

crtPoint.show();

crtPoint.setCentralX(0);

crtPoint.setCentralY(0);

UES.setViewOffsetX(90);

this.setKeyListener(this);

UES.pushKeyBoardIO(this);

for (int i = 0;i < times;i++){

generateNew();

}

}

@Override

public void doKeyBord(KeyFactor whom, int keyCode, Boolean ispressed) {

//键盘IO的方式同上例

if(ispressed){

if(keyCode == KeyEvent.VK_SPACE){

generateNew();

} else if(keyCode == KeyEvent.VK_A){

for (int i = 0;i < 100;i++){

generateNew();

}

} else if(keyCode == KeyEvent.VK_B){

for (int i = 0;i < 1000;i++){

generateNew();

}

}

}

}

public void generateNew(){

float nx,ny;

float ox = crtPoint.getCentralX()/150f,oy = (600 - crtPoint.getCentralY())/60f;

//这里做了OPENGL坐标转换,在设置新点位置时对应反转。

double code = 100.0 * RandomSet.getRandomFloatIn_1();

//随机浮点数数0~100

if(code >= 0&&code <= 1){

nx = 0;

ny = 0.00f * ox + 0.16f * oy;

} else if(code > 1&& code <= 86){

nx = 0.85f*ox + 0.04f*oy;

ny = -0.04f*ox + 0.85f*oy + 1.6f;

} else if(code > 86&& code <= 93){

nx = 0.2f*ox - 0.26f*oy;

ny = 0.23f*ox + 0.22f*oy + 1.6f;

} else{

nx = -0.15f*ox + 0.28f*oy;

ny = 0.26f*ox + 0.24f*oy + 0.44f;

}

Obj newPoint = UES.creatObj(UESI.BGIndex);

newPoint.addGLPoint("70DBDB",0,0);

newPoint.setColor(Color.GREEN);

newPoint.setCentralX(nx*150f);

//将之前的坐标变换抵消

newPoint.setCentralY(600 - ny*60f);

newPoint.show();

crtPoint = newPoint;

//设置新点为当前点。

}

public static void main(String[] args) {

UESI ues = new R();

new Barnsleyfern(ues,0);

}

}

[模拟结果]

7ec16b4839e0ee125a403053fbf33fd6.png

156172698f4985854b6dea45265fbff0.png

1050b51814f8e0ebc7afc09a6aa04d8b.png

总结

以上就是本文关于Java Chaos Game噪声游戏实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LibNoise分形噪声函数库的JAVA翻译版,个人开发,仅供参考。 包中包含: 异常模块: noise.Exception noise.ExceptionInvalidParam 无效的参数异常。 noise.ExceptionNoModule 无模块异常,无法检索到该源模块 noise.ExceptionOutOfMemory noise.ExceptionUnknown 模型模块: noise.model.Line 线 noise.model.Plane 平面 noise.model.Sphere 球体 noise.model.Cylinder 圆柱 发生器模块: noise.module.Perlin 培林噪声 noise.module.RidgedMulti 脊多重分形噪声 noise.module.Billow 巨浪 value = |perlin_value|*2-1.0; noise.module.Voronoi 细胞噪声,Voronoi图 noise.module.Const 常量 value = const; noise.module.Cylinders 圆柱 noise.module.Checkerboard 棋盘格 value = (floor(x) & 1 ^ floor(y) & 1 ^ floor(z) & 1) != 0 ? -1.0 : 1.0; noise.module.Spheres 球体 选择器模块: noise.module.Select 选择 noise.module.Blend 混合 value = ((1.0 - (modules[3].value+1)/2) * modules[0].value) + ((modules[3].value+1)/2 * modules[1].value); 修饰器模块: noise.module.Invert 倒置 value = -value; noise.module.Abs 绝对值 value = |value|; noise.module.Clamp 截取 value = (value < lowerBound ?lowerBound : value) or (value > upperBound ?upperBound : value);lowerBound:下截取值;upperBound:上截取值 noise.module.Curve 曲线 value = noise.module.Curve.ControlPoint 控制点 noise.module.ScaleBias 偏移缩放, value = value*scale+offset noise.module.Turbulence 湍流 value = modules[0].getValue(x+modules[1].value * power,y+modules[2].value * power,z+modules[3].value * power); noise.module.Exponent 指数 value = (pow(abs((value + 1.0) / 2.0), exponent) * 2.0 - 1.0); 组合模块: noise.module.Add 添加 value = modules[0].value+modules[1].value; noise.module.Max 最大值 value = max(value); noise.module.Min 最小值 value = min(value); noise.module.Multiply 乘法 value = modules[0].value * modules[1].value; noise.module.Power 权重 value = pow(modules[0].value , modules[1].value); 变压模块: noise.module.Displace 位移替换,扭曲 value = modules[0].getValue(x+modules[1].value,y+modules[2].value,z+modules[3].value); noise.module.RotatePoint 点旋转 noise.module.ScalePoint 点缩放,轴缩放 value = modules[0].getValue (x * xScale, y * yScale,z * zScale); noise.module.Terrace 露台,梯台 noise.module.TranslatePoint 位移变换 value = modules[0].getValue (x * xTranslation, y * yTranslation,z * zTranslation); 其他: noise.module.Cache 缓存 value = noise.module.Module 噪声模块基类 如果发现有要更改的地方,请发邮件给我,或者本人QQ:343179390,欢迎技术探讨

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值