本文主要是介绍3D模拟自然——山体,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
算法上使用分形插值算法。渲染上,效率和扩展性中最理想的是用shader,但为了方便也可以用封装好的pixmap或shapeRenderer。这里用pixmap来绘制3d山。值得一提,1.6.1API:Color.toIntBits(int r,int g,int b,int a)是错的,参数位置前后倒了,导致山体一片红,所以顺着对的修改完毕。可以重置,修改blend模式以及精细程度。
以下是代码和效果图。
(可以看到n值为2倍后内存消耗增加不止1倍,渲染算法上是需要改进的)
package indi.dawn.ff.work;import java.util.StringTokenizer;import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Blending;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.utils.Disposable;class MountainC extends Actor implements Disposable{ShapeRenderer jj;int n = 32, n1, h,w,h2,w2, mx0,my0, xPol[],yPol[], iCol[][][];double rnd, fiX = .2, fiY = .3, dfi = .01, scale = .8, m20,m21,m22;double vert[][][], vert1[][][], Norm[][][][], Norm1z[][][], M[];Color col[][];boolean painted;Texture buffImage;Pixmap buffGraphics;InputListener ip;public MountainC(){ip=new InputListener(){@Overridepublic boolean touchDown(InputEvent event, float x, float y,int pointer, int button) {// TODO Auto-generated method stubmx0 = (int) x; my0 = (int) y;if ( Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) ){setup();
// repaint();}if ( Gdx.input.isKeyPressed(Input.Keys.ALT_LEFT) ){if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) ){ n /= 2; if (n < 1) n = 1;}else n *= 2;setup();
// repaint();}if(Gdx.app.getType()==ApplicationType.Android){if (pointer==1){n *= 2;setup();
// repaint();}if (pointer==2 ){ n /= 2; if (n < 1) n = 1;}}return true;}@Overridepublic void touchDragged(InputEvent event, float x, float y,int pointer) {// TODO Auto-generated method stubint x1 = (int) x; int y1 = (int) y;if ( Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT) ) scale *= Math.exp(-(y1 - my0)/(double)w);else fiX += dfi*(y1 - my0);fiY += dfi*(x1 - mx0); mx0 = x1; my0 = y1;rotate();
// repaint();}};init();/*for(int i=0;i<4;i++){for(Color c:col[i]){System.out.println(c.toIntBits());}}*/}private Color calCol(int r,int g,int b){return new Color(Color.toIntBits(255, b, g, r));};int getN(){return 32;}Color getCol(){return Color.WHITE;}Color bgColor;int pmWidth=600,pmHeight=800;public void init(){
// w=(int) getWidth();h=(int) getHeight();w = pmWidth; h = pmHeight; w2 = w/2; h2 = h/2;
// n=getN();xPol = new int[3]; yPol = new int[3];buffGraphics=new Pixmap(w, h, Pixmap.Format.RGB888);
// buffGraphics.setBlending(Blending.SourceOver);buffImage= new Texture(buffGraphics);col = new Color[4][256];for (int i = 0; i < 256; i++){col[0][i] = calCol(0, 0, i);col[1][i] = calCol(0, (i*220)/256, 0);col[2][i] = calCol((i*150)/256, (i*150)/256, (i*50)/256);col[3][i] = calCol(i, i, i);}for(int i=0;i<4;i++){for(Color c:col[i]){System.out.println(c);}}bgColor=getCol();if(bgColor==null)bgColor=Color.WHITE;addListener(ip);setup();}public double R(){ return rnd*(Math.random()-.5);}public void setup(){rnd = 1;n1 = n+1;iterate();vert = new double[n1][n1][3]; vert1 = new double[n1][n1][2];double dx = w/(double)n;int t = 0;for (int i = 0; i < n1; i++) for (int j = 0; j < n1; j++){vert[i][j][0] = dx*i - w2; vert[i][j][2] = dx*j - w2;double mi = M[t++];if (mi < 0) mi = .01*Math.random();vert[i][j][1] = w*mi - w2/2;}Norm = new double[n1][n1][2][3]; Norm1z = new double[n1][n1][2];iCol = new int[n][n][2];for (int i = 0; i < n; i++)for (int j = 0; j < n; j++){double s =((vert[i][j][1] + vert[i+1][j][1] + vert[i+1][j+1][1])/3 + w2/2)/w;if (s < .01) iCol[i][j][0] = 0;else if (s+.1*Math.random() > .35) iCol[i][j][0] = 3;else if (s+.1*Math.random() > .15) iCol[i][j][0] = 2;else iCol[i][j][0] = 1;s = ((vert[i][j][1] + vert[i][j+1][1] + vert[i+1][j+1][1])/3 + w2/2)/w;if (s < .01) iCol[i][j][1] = 0;else if (s+.1*Math.random() > .35) iCol[i][j][1] = 3;else if (s+.1*Math.random() > .15) iCol[i][j][1] = 2;else iCol[i][j][1] = 1;Norm[i][j][0][0] = vert[i][j][1] - vert[i+1][j][1];Norm[i][j][0][1] = dx;Norm[i][j][0][2] = vert[i+1][j][1] - vert[i+1][j+1][1];double mod = Math.sqrt(Norm[i][j][0][0]*Norm[i][j][0][0] + Norm[i][j][0][1]*Norm[i][j][0][1] + Norm[i][j][0][2]*Norm[i][j][0][2]) / 255.5;Norm[i][j][0][0] /= mod; Norm[i][j][0][1] /= mod; Norm[i][j][0][2] /= mod;Norm[i][j][1][0] = vert[i][j+1][1] - vert[i+1][j+1][1];Norm[i][j][1][1] = dx;Norm[i][j][1][2] = vert[i][j][1] - vert[i][j+1][1];mod = Math.sqrt(Norm[i][j][1][0]*Norm[i][j][1][0] + Norm[i][j][1][1]*Norm[i][j][1][1] + Norm[i][j][1][2]*Norm[i][j][1][2]) / 255.5;Norm[i][j][1][0] /= mod; Norm[i][j][1][1] /= mod; Norm[i][j][1][2] /= mod;}rotate();}public void iterate(){int nc=n, Max=n1*n1, ncn1;double Min=-1;M = new double[Max];for (int i=n+2; i < n*n1-1; i++) M[i] = Min;for (int i=2*n1; i < n*n1; i += n1) M[i] = M[i-1] = 0;while ( (nc /= 2) >= 1){ncn1 = nc*n1;for (int j=ncn1; j < Max; j += ncn1+ncn1){for (int i= nc; i < n; i += nc+nc){if (M[i+j]==Min)M[i+j] = (M[i+j+nc-ncn1] + M[i+j-nc+ncn1])/2.+R();if (M[i+j+nc]==Min)M[i+j+nc] = (M[i+j+nc+ncn1] + M[i+j+nc-ncn1])/2.+R();if (M[i+j+ncn1]==Min)M[i+j+ncn1] = (M[i+j-nc+ncn1] + M[i+j+nc+ncn1])/2.+R(); }}rnd /= 2.;}}public void rotate(){double ct = Math.cos(fiX), cf = Math.cos(fiY),st = Math.sin(fiX), sf = Math.sin(fiY),m00 = scale*cf, m02 = scale*sf,m10 = scale*st*sf, m11 = scale*ct, m12 = -scale*st*cf;m20 = -ct*sf; m21 = st; m22 = ct*cf;for (int i = 0; i < n1; i++)for (int j = 0; j < n1; j++){vert1[i][j][0] = m00*vert[i][j][0] + m02*vert[i][j][2];vert1[i][j][1] = m10*vert[i][j][0] + m11*vert[i][j][1] + m12*vert[i][j][2];}for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)for (int k = 0; k < 2; k++)Norm1z[i][j][k] = m20*Norm[i][j][k][0] + m21*Norm[i][j][k][1] +m22*Norm[i][j][k][2];painted = false;}@Overridepublic void draw(Batch batch, float parentAlpha) {// TODO Auto-generated method stubif ( !painted ){if(buffImage!=null){buffImage.dispose();buffImage=null;/* buffGraphics.dispose();buffGraphics=new Pixmap(w, h, Format.RGB888);*/}
// buffGraphics.dispose();
// Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);buffGraphics.setColor(Color.WHITE);buffGraphics.fill();int ib=0, ie=n, sti=1, jb=0, je=n, stj=1;if (m20 < 0){ ib = n; ie = -1; sti = -1;}if (m22 < 0){ jb = n; je = -1; stj = -1;}for (int i = ib; i != ie; i += sti)for (int j = jb; j != je; j += stj){if (Norm1z[i][j][0] > 0){xPol[0] = w2 + (int)vert1[i][j][0];xPol[1] = w2 + (int)vert1[i+1][j][0];xPol[2] = w2 + (int)vert1[i+1][j+1][0];yPol[0] = h2 - (int)vert1[i][j][1];yPol[1] = h2 - (int)vert1[i+1][j][1];yPol[2] = h2 - (int)vert1[i+1][j+1][1];System.out.println(iCol[i][j][0]+"?"+(int)(Norm1z[i][j][0]));System.out.println(col[iCol[i][j][0]][(int)(Norm1z[i][j][0])].toString());buffGraphics.setColor(col[iCol[i][j][0]][(int)(Norm1z[i][j][0])]);buffGraphics.fillTriangle(xPol[0], yPol[0], xPol[1], yPol[1], xPol[2], yPol[2]);
// buffGraphics.fillPolygon(xPol,yPol, 3);}if (Norm1z[i][j][1] > 0){xPol[0] = w2 + (int)vert1[i][j][0];xPol[1] = w2 + (int)vert1[i][j+1][0];xPol[2] = w2 + (int)vert1[i+1][j+1][0];yPol[0] = h2 - (int)vert1[i][j][1];yPol[1] = h2 - (int)vert1[i][j+1][1];yPol[2] = h2 - (int)vert1[i+1][j+1][1];buffGraphics.setColor(col[iCol[i][j][1]][(int)(Norm1z[i][j][1])]);buffGraphics.fillTriangle(xPol[0], yPol[0], xPol[1], yPol[1], xPol[2], yPol[2]);} }painted = true;buffImage=new Texture(buffGraphics, true);}
// Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);batch.draw(buffImage, getX(), getY());/*if(!painted){buffGraphics.setColor(col(255, 0, 0));buffGraphics.fill();buffImage=new Texture(buffGraphics);painted = true;}batch.draw(buffImage, getX(), getY());*/// g.drawImage(buffImage, 0, 0, this);}@Overridepublic void dispose() {// TODO Auto-generated method stubbuffGraphics.dispose();buffImage.dispose();}/***************************************************//*public void init2(){w = getSize().width; h = getSize().height; w2 = w/2; h2 = h/2;String s=getParameter("N"); if (s != null) n = Integer.parseInt(s);xPol = new int[3]; yPol = new int[3];buffImage = createImage(w, h); buffGraphics = buffImage.getGraphics();col = new Color[4][256];for (int i = 0; i < 256; i++){col[0][i] = new Color(0, 0, i);col[1][i] = new Color(0, (i*220)/256, 0);col[2][i] = new Color((i*150)/256, (i*150)/256, (i*50)/256);col[3][i] = new Color(i, i, i);}s = getParameter("bgColor"); if (s != null){StringTokenizer st = new StringTokenizer(s);int red = Integer.parseInt(st.nextToken());int green = Integer.parseInt(st.nextToken());int blue = Integer.parseInt(st.nextToken());setBackground( new Color(red, green, blue));}else setBackground(new Color(255,255,255));addMouseListener(this);addMouseMotionListener(this);setup();for(int i=0;i<4;i++){for(Color c:col[i]){int a=c.getRed();int b=c.getGreen();int g=c.getBlue();int r= c.getAlpha();int m=(a << 24) | (b << 16) | (g << 8) | r;System.out.println(m);}}}*/public void rotate2(){double ct = Math.cos(fiX), cf = Math.cos(fiY),st = Math.sin(fiX), sf = Math.sin(fiY),m00 = scale*cf, m02 = scale*sf,m10 = scale*st*sf, m11 = scale*ct, m12 = -scale*st*cf;m20 = -ct*sf; m21 = st; m22 = ct*cf;for (int i = 0; i < n1; i++)for (int j = 0; j < n1; j++){vert1[i][j][0] = m00*vert[i][j][0] + m02*vert[i][j][2];vert1[i][j][1] = m10*vert[i][j][0] + m11*vert[i][j][1] + m12*vert[i][j][2];}for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)for (int k = 0; k < 2; k++)Norm1z[i][j][k] = m20*Norm[i][j][k][0] + m21*Norm[i][j][k][1] +m22*Norm[i][j][k][2];painted = false;}public void iterate2(){int nc=n, Max=n1*n1, ncn1;double Min=-1;M = new double[Max];for (int i=n+2; i < n*n1-1; i++) M[i] = Min;for (int i=2*n1; i < n*n1; i += n1) M[i] = M[i-1] = 0;while ( (nc /= 2) >= 1){ncn1 = nc*n1;for (int j=ncn1; j < Max; j += ncn1+ncn1){for (int i= nc; i < n; i += nc+nc){if (M[i+j]==Min)M[i+j] = (M[i+j+nc-ncn1] + M[i+j-nc+ncn1])/2.+R();if (M[i+j+nc]==Min)M[i+j+nc] = (M[i+j+nc+ncn1] + M[i+j+nc-ncn1])/2.+R();if (M[i+j+ncn1]==Min)M[i+j+ncn1] = (M[i+j-nc+ncn1] + M[i+j+nc+ncn1])/2.+R(); }}rnd /= 2.;}}public void setup2(){rnd = 1;n1 = n+1;iterate();vert = new double[n1][n1][3]; vert1 = new double[n1][n1][2];double dx = w/(double)n;int t = 0;for (int i = 0; i < n1; i++) for (int j = 0; j < n1; j++){vert[i][j][0] = dx*i - w2; vert[i][j][2] = dx*j - w2;double mi = M[t++];if (mi < 0) mi = .01*Math.random();vert[i][j][1] = w*mi - w2/2;}Norm = new double[n1][n1][2][3]; Norm1z = new double[n1][n1][2];iCol = new int[n][n][2];for (int i = 0; i < n; i++)for (int j = 0; j < n; j++){double s =((vert[i][j][1] + vert[i+1][j][1] + vert[i+1][j+1][1])/3 + w2/2)/w;if (s < .01) iCol[i][j][0] = 0;else if (s+.1*Math.random() > .35) iCol[i][j][0] = 3;else if (s+.1*Math.random() > .15) iCol[i][j][0] = 2;else iCol[i][j][0] = 1;s = ((vert[i][j][1] + vert[i][j+1][1] + vert[i+1][j+1][1])/3 + w2/2)/w;if (s < .01) iCol[i][j][1] = 0;else if (s+.1*Math.random() > .35) iCol[i][j][1] = 3;else if (s+.1*Math.random() > .15) iCol[i][j][1] = 2;else iCol[i][j][1] = 1;Norm[i][j][0][0] = vert[i][j][1] - vert[i+1][j][1];Norm[i][j][0][1] = dx;Norm[i][j][0][2] = vert[i+1][j][1] - vert[i+1][j+1][1];double mod = Math.sqrt(Norm[i][j][0][0]*Norm[i][j][0][0] + Norm[i][j][0][1]*Norm[i][j][0][1] + Norm[i][j][0][2]*Norm[i][j][0][2]) / 255.5;Norm[i][j][0][0] /= mod; Norm[i][j][0][1] /= mod; Norm[i][j][0][2] /= mod;Norm[i][j][1][0] = vert[i][j+1][1] - vert[i+1][j+1][1];Norm[i][j][1][1] = dx;Norm[i][j][1][2] = vert[i][j][1] - vert[i][j+1][1];mod = Math.sqrt(Norm[i][j][1][0]*Norm[i][j][1][0] + Norm[i][j][1][1]*Norm[i][j][1][1] + Norm[i][j][1][2]*Norm[i][j][1][2]) / 255.5;Norm[i][j][1][0] /= mod; Norm[i][j][1][1] /= mod; Norm[i][j][1][2] /= mod;}rotate();}
}
这篇关于3D模拟自然——山体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!