// 3D random landscape, Evgeny Demidov 19 Feb 2002 import java.awt.*; import java.awt.event.*; import java.util.StringTokenizer; public class @file extends java.applet.Applet implements ItemListener, ActionListener, MouseListener, MouseMotionListener{ int n = 32, n1, Rc = 4, h,w,h2,w2, mx0,my0, xPol[],yPol[], iCol[][][]; double Vp = 0, Vs, Vmin, Vmax, fiX = .8, fiY = .3, dfi = .01, scale = .8, m20,m21,m22; double vert[][][], vert1[][][], Norm[][][][], Norm1z[][][], M[]; Image buffImage; Graphics buffGraphics; Choice chRc, chL; Label lbRc, lbL; Button btNew; Color[][] col; boolean painted; public void init(){ w = getSize().width - 30; h = getSize().height; w2 = w/2; h2 = h/2; String s=getParameter("N"); if (s != null) n = Integer.parseInt(s); s=getParameter("Rc"); if (s != null) Rc = Integer.parseInt(s); xPol = new int[3]; yPol = new int[3]; buffImage = createImage(w, h); buffGraphics = buffImage.getGraphics(); col = new Color[2][256]; for (int i = 0; i < 256; i++){ col[0][i] = new Color(0, 0, i); col[1][i] = new Color(0, i, 0);} 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)); lbL = new Label("L", Label.RIGHT); add(lbL); chL = new Choice(); for (int i = 0, r = 32; i < 4; i++){ chL.addItem(Integer.toString(r)); r *= 2;} chL.select("" + n); chL.addItemListener(this); add(chL); lbRc = new Label("Rc", Label.RIGHT); add(lbRc); chRc = new Choice(); for (int i = 0, r = 1; i < 5; i++){ chRc.addItem(Integer.toString(r)); r *= 2;} chRc.select("" + Rc); chRc.addItemListener(this); add(chRc); btNew = new Button("New"); btNew.addActionListener(this); add(btNew); addMouseListener(this); addMouseMotionListener(this); landscape(); make3D(); } public void make3D(){ vert = new double[n1][n1][3]; vert1 = new double[n1][n1][2]; double dx = w/(double)n; 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 m = M[i+n1*j]; if (m < Vp) m = Vp; vert[i][j][1] = w*m - 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 < Vp+.0001) iCol[i][j][0] = 0; 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 < Vp+.0001) iCol[i][j][1] = 0; 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 landscape(){ n1 = n+1; int nc=n, Max=n1*n1, ncn1; M = new double[Max]; double f[][] = new double[n1+64][n1+64]; for (int i = 0; i < n1+64; i++) for (int j = 0; j < n1+64; j++) f[i][j] = 2*Math.random() - 1; // f[100][100] = 1; int Lc = 2*Rc; double Rc2 = Rc*Rc; double G[][] = new double[32][32]; G[0][0] = 1; for (int i = 1; i < Lc; i++){ G[0][i] = Math.exp(-(i*i/Rc2)); for (int j = 1; j <= i; j++) G[j][i] = G[0][i]*G[0][j];} Vs = 0; Vmin = 100; Vmax = -100; int t = 0, n33 = n1+32; for (int i = 32; i < n33; i++){ for (int j = 32; j < n33; j++){ double s = G[0][0]*f[i][j]; for (int m = 1; m < Lc; m++){ int im = i+m, i_m = i-m, jm = j+m, j_m = j-m; s += G[0][m]*(f[im][j]+f[i_m][j]+f[i][jm]+f[i][j_m]) + G[m][m]*(f[im][jm]+f[i_m][jm]+f[im][j_m]+f[i_m][j_m]); for (int n = 1; n < m; n++){ int in = i+n, i_n = i-n, jn = j+n, j_n = j-n; s += G[n][m]*(f[im][jn]+f[i_m][jn]+f[im][j_n]+f[i_m][j_n] + f[in][jm]+f[i_n][jm]+f[in][j_m]+f[i_n][j_m]);}} s *= 0.02; M[t++] = s; Vs += s; if (s > Vmax) Vmax = s; if (s < Vmin) Vmin = s;}} Vs /= Max; } public void destroy() { removeMouseListener(this); removeMouseMotionListener(this); } public void actionPerformed(ActionEvent e){ landscape(); make3D(); repaint(); } public void itemStateChanged(ItemEvent e){ Object src = e.getSource(); if (src == chRc) Rc = Integer.parseInt(chRc.getSelectedItem()); if (src == chL) n = Integer.parseInt(chL.getSelectedItem()); landscape(); make3D(); repaint(); } public void mouseClicked(MouseEvent e){} // event handling public void mousePressed(MouseEvent e) { mx0 = e.getX(); my0 = e.getY(); e.consume(); } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} public void mouseDragged(MouseEvent e) { int x1 = e.getX(); int y1 = e.getY(); if( e.getX() < w){ if ( e.isShiftDown() ) scale *= Math.exp(-(y1 - my0)/(double)w); else fiX += dfi*(y1 - my0); fiY += dfi*(x1 - mx0); mx0 = x1; my0 = y1; rotate();} else{ Vp = Vmax - y1*(Vmax-Vmin)/h; make3D();} repaint(); e.consume(); } 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; } public void paint(Graphics g) { if ( !painted ){ buffGraphics.clearRect(0, 0, w, h); 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]; buffGraphics.setColor(col[iCol[i][j][0]][(int)(Norm1z[i][j][0])]); 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.fillPolygon(xPol,yPol, 3);} } painted = true;} g.drawImage(buffImage, 0, 0, this); g.setColor(Color.blue); g.fillRect(w+10,0, 20,h); g.setColor(Color.white); int y = h - (int)(h*(Vs-Vmin)/(Vmax-Vmin)); g.drawLine(w+10,y, w+30,y); g.setColor(Color.yellow); y = h - (int)(h*(Vp-Vmin)/(Vmax-Vmin)); g.drawLine(w+10,y, w+30,y); // showStatus( "n=" + n); } public void update(Graphics g){ paint(g); } }