OpenGl(jogl)分形算法生成树
程序员文章站
2023-12-27 14:08:15
...
一,配置环境
1.需要的jar包
二,代码
1,GlPoint类
/**
* 自定义的点类,存储x和y值
* @author mcl
*
*/
public class GlPoint {
/*x坐标*/
float x = 0.00f;
/*y坐标*/
float y = 0.00f;
public GlPoint() {
}
public GlPoint(float x, float y) {
this.x = x;
this.y = y;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
}
2,TreeAnimation类
import javax.swing.JFrame;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
/**
* 实现GLEventListener接口
* @author mcl
*
*/
public class TreeAnimation implements GLEventListener{
static final String START_POINT_X = "START_POINT_X";
static final String START_POINT_Y = "START_POINT_Y";
static final String END_POINT_X = "END_POINT_X";
static final String END_POINT_Y = "END_POINT_Y";
double partition = 10.0;
JSONArray jsonArray = new JSONArray();
JSONArray jsonArray1 = new JSONArray();
JSONArray jsonArray2 = new JSONArray();
JSONArray jsonArray3 = new JSONArray();
JSONArray jsonArray4 = new JSONArray();
JSONArray jsonArray5 = new JSONArray();
JSONArray jsonArray6 = new JSONArray();
JSONArray jsonArray7 = new JSONArray();
@Override
public void init(GLAutoDrawable drawable) {
final GL2 gl = drawable.getGL().getGL2();
GlPoint start = new GlPoint(0, -0.70f);
GlPoint end = new GlPoint(0, -0.30f);
int level = 6;
double angle = 35.0 * (Math.PI / 180);
double smallAngle = -10.0 * (Math.PI / 180);
double smallAngle1 = -5.0 * (Math.PI / 180);
double smallAngle2 = 0.0 * (Math.PI / 180);
double smallAngle3 = 5.0 * (Math.PI / 180);
double smallAngle4 = 10.0 * (Math.PI / 180);
double rate = 0.8;
double bottom = -10.0;
jsonArray = createPointsOfTree(12, start, end, angle, rate, smallAngle);
jsonArray1 = createPointsOfTree(12, start, end, angle, rate, smallAngle1);
jsonArray2 = createPointsOfTree(12, start, end, angle, rate, smallAngle2);
jsonArray3 = createPointsOfTree(12, start, end, angle, rate, smallAngle3);
jsonArray4 = createPointsOfTree(12, start, end, angle, rate, smallAngle4);
}
@Override
public void display(GLAutoDrawable drawable) {
final GL2 gl = drawable.getGL().getGL2();
GlPoint start = new GlPoint(0, -1.0f);
GlPoint end = new GlPoint(0, -0.30f);
gl.glBegin (GL2.GL_LINES);//static field 多组双顶点线段
gl.glVertex3f(start.getX(), start.getY(), 1);
gl.glVertex3f(end.getX(), end.getY(), 1);
gl.glEnd();
gl.glClear(GL2.GL_STENCIL_BUFFER_BIT);
drawCenterTree(gl);
}
private void drawRightEndTree(GL2 gl2) {
GL2 gl = gl2;
for (int i = 0; i < jsonArray4.size(); i++) {
JSONObject object = (JSONObject) jsonArray4.get(i);
float startx = object.getFloatValue(START_POINT_X);
float starty = object.getFloatValue(START_POINT_Y);
float endx = object.getFloatValue(END_POINT_X);
float endy = object.getFloatValue(END_POINT_Y);
gl.glBegin (GL2.GL_LINES);//static field 多组双顶点线段
gl.glVertex3f(startx, starty, 1);
gl.glVertex3f(endx, endy, 1);
gl.glEnd();
}
}
private void drawRightTree(GL2 gl2) {
GL2 gl = gl2;
for (int i = 0; i < jsonArray3.size(); i++) {
JSONObject object = (JSONObject) jsonArray3.get(i);
float startx = object.getFloatValue(START_POINT_X);
float starty = object.getFloatValue(START_POINT_Y);
float endx = object.getFloatValue(END_POINT_X);
float endy = object.getFloatValue(END_POINT_Y);
gl.glBegin (GL2.GL_LINES);//static field 多组双顶点线段
gl.glVertex3f(startx, starty, 1);
gl.glVertex3f(endx, endy, 1);
gl.glEnd();
}
}
private void drawCenterTree(GL2 gl2) {
System.out.println("TreeAnimation.drawCenterTree()");
GL2 gl = gl2;
for (int i = 0; i < jsonArray2.size(); i++) {
JSONObject object = (JSONObject) jsonArray2.get(i);
float startx = object.getFloatValue(START_POINT_X);
float starty = object.getFloatValue(START_POINT_Y);
float endx = object.getFloatValue(END_POINT_X);
float endy = object.getFloatValue(END_POINT_Y);
gl.glBegin (GL2.GL_LINES);//static field 多组双顶点线段
gl.glVertex3f(startx, starty, 1);
gl.glVertex3f(endx, endy, 1);
gl.glEnd();
}
}
private void drawLeft2Tree(GL2 gl2) {
GL2 gl = gl2;
for (int i = 0; i < jsonArray1.size(); i++) {
JSONObject object = (JSONObject) jsonArray1.get(i);
float startx = object.getFloatValue(START_POINT_X);
float starty = object.getFloatValue(START_POINT_Y);
float endx = object.getFloatValue(END_POINT_X);
float endy = object.getFloatValue(END_POINT_Y);
gl.glBegin (GL2.GL_LINES);//static field 多组双顶点线段
gl.glVertex3f(startx, starty, 1);
gl.glVertex3f(endx, endy, 1);
gl.glEnd();
}
}
private void drawLeftTree(GL2 gl2) {
GL2 gl = gl2;
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject object = (JSONObject) jsonArray.get(i);
float startx = object.getFloatValue(START_POINT_X);
float starty = object.getFloatValue(START_POINT_Y);
float endx = object.getFloatValue(END_POINT_X);
float endy = object.getFloatValue(END_POINT_Y);
gl.glBegin (GL2.GL_LINES);//static field 多组双顶点线段
gl.glVertex3f(startx, starty, 1);
gl.glVertex3f(endx, endy, 1);
gl.glEnd();
}
}
@Override
public void dispose(GLAutoDrawable arg0) {
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height ) {
}
public static void main(String[] args) {
//轮廓,剖面,外形
final GLProfile profile = GLProfile.get(GLProfile.GL2);
//性能
GLCapabilities capabilities = new GLCapabilities(profile);
/*The canvas(画布)*/
final GLCanvas glcanvas = new GLCanvas(capabilities);
/*定义一条线*/
TreeAnimation l = new TreeAnimation();
/*设置监听器*/
glcanvas.addGLEventListener(l);
/*设置画布的宽,高*/
glcanvas.setSize(1200, 1200);
/*创建一个框架*/
final JFrame frame = new JFrame ("straight Line");
/*把画布添加到框架中*/
frame.getContentPane().add(glcanvas);
/*优先尺寸*/
frame.setSize(frame.getContentPane().getPreferredSize());
frame.setVisible(true);
}//end of main
/*计算向右偏移之后的向量*/
public static float computeToRightXVector(float xVertor, float yVertor, double tmpSin, double tmpCos, double rate) {
// 计算右边的点
return (float)((xVertor * tmpCos + yVertor * tmpSin) * rate);//11/20
}
/*计算向右偏移之后的y向量*/
public static float computeToRightYVector(float xVertor, float yVertor, double tmpSin, double tmpCos, double rate) {
// 计算右边的点
return (float)((-xVertor * tmpSin + yVertor * tmpCos) * rate);
}
/*计算向左偏移之后的向量*/
public static float computeToLeftXVector(float xVertor, float yVertor, double tmpSin, double tmpCos, double rate) {
// 计算左边的点
return (float)((xVertor * tmpCos - yVertor * tmpSin) * rate);//11/20
}
/*计算向左偏移之后的y向量*/
public static float computeToLeftYVector(float xVertor, float yVertor, double tmpSin, double tmpCos, double rate) {
// 计算左边的点
return (float)((xVertor * tmpSin + yVertor * tmpCos) * rate);
}
public JSONArray createPointsOfTree(int leveltmp,//递归层数
GlPoint fatherStart,//父线段的起始点
GlPoint fatherEnd, //父线段的结束点
double leafAngle, //分支和主干的角度
double rate,//分支占主干的比率
double smallAngle//树每次偏移的角度
) {
int level = leveltmp;
//计算父向量
float xVertor = fatherEnd.getX() - fatherStart.getX();
float yVertor = fatherEnd.getY() - fatherStart.getY();
//主干偏移的小角度
double mainBodySin = Math.sin(smallAngle);
double mainBodyCos = Math.cos(smallAngle);
//右边偏移的角度
double tmpSin = Math.sin(leafAngle);
double tmpCos = Math.cos(leafAngle);
//计算主干偏移之后的向量
float mainXVertor = computeToRightXVector(xVertor, yVertor, mainBodySin, mainBodyCos, rate);
float mainYVertor = computeToRightYVector(xVertor, yVertor, mainBodySin, mainBodyCos, rate);
GlPoint mainStart = fatherEnd;
GlPoint mainEnd = new GlPoint(fatherEnd.getX() + mainXVertor, fatherEnd.getY() + mainYVertor);
JSONObject mainBody = new JSONObject();
mainBody.put(START_POINT_X,mainStart.getX());
mainBody.put(START_POINT_Y, mainStart.getY());
mainBody.put(END_POINT_X, mainEnd.getX());
mainBody.put(END_POINT_Y, mainEnd.getY());
//计算偏移后,左边枝干的向量
float leftXVector = computeToLeftXVector(mainXVertor, mainYVertor, tmpSin, tmpCos, rate);
float leftYVector = computeToLeftYVector(mainXVertor, mainYVertor, tmpSin, tmpCos, rate);
GlPoint leftStart = fatherEnd;
GlPoint leftEnd = new GlPoint(fatherEnd.getX() + leftXVector, fatherEnd.getY() + leftYVector);
JSONObject leftBody = new JSONObject();
leftBody.put(START_POINT_X,leftStart.getX());
leftBody.put(START_POINT_Y, leftStart.getY());
leftBody.put(END_POINT_X, leftEnd.getX());
leftBody.put(END_POINT_Y, leftEnd.getY());
//计算偏移后,右边的枝干向量
float rightXVector = computeToRightXVector(mainXVertor, mainYVertor, tmpSin, tmpCos, rate);
float rightVector = computeToRightYVector(mainXVertor, mainYVertor, tmpSin, tmpCos, rate);
GlPoint rightStart = fatherEnd;
GlPoint rightEnd = new GlPoint(fatherEnd.getX() + rightXVector, fatherEnd.getY() + rightVector);
JSONObject rightBody = new JSONObject();
rightBody.put(START_POINT_X,rightStart.getX());
rightBody.put(START_POINT_Y, rightStart.getY());
rightBody.put(END_POINT_X, rightEnd.getX());
rightBody.put(END_POINT_Y, rightEnd.getY());
JSONArray result = new JSONArray();
result.add(mainBody);
result.add(leftBody);
result.add(rightBody);
level--;
if (level > 0) {
//主干
JSONArray result1 = createPointsOfTree(level - 1, mainStart, mainEnd, leafAngle, rate, smallAngle);
//左边
JSONArray result2 = createPointsOfTree(level - 1, leftStart, leftEnd, leafAngle, rate, smallAngle);
//右边
JSONArray result3 = createPointsOfTree(level - 1, rightStart, rightEnd, leafAngle, rate, smallAngle);
for (int i = 0; i < result1.size(); i++) {
JSONObject object = (JSONObject) result1.get(i);
result.add(object);
}
for (int i = 0; i < result2.size(); i++) {
JSONObject object = (JSONObject) result2.get(i);
result.add(object);
}
for (int i = 0; i < result3.size(); i++) {
JSONObject object = (JSONObject) result3.get(i);
result.add(object);
}
}
return result;
}
}
三、效果图
这就是程序运行之后的效果图,此树还可以向两边偏移,只需要设置一下角度就可以