Algorithms   

Making 3D Landscapes

Writing a program to make random 3D Landscapes based on plasma fractals is not as hard as it might seem. Below we provide a full code for our Landscape applet. All you need to know to write a program like this is a little trig for getting the 3D look and also know how to make plasma fractals, which is described in previous chapter. Of course to understand our code you need to know Java, but we didn't use any complex technicues for it. If you need help on Java visit it's creators.
Note: Our code is not copyrighted and in fact we encourage you to add to it, and send us any ideas or code you think should be put in our applet.

import java.applet.*;
import java.awt.*;

public class landscape extends Applet {
Image offscr;
Graphics offscrgr;
Color cols[]={new Color(0,0,0),new Color(60,60,60),new Color(64,60,60),new Color(72,60,60),new Color(76,56,56),new Color(84,56,56),new Color(88,52,52),new Color(96,52,52),new Color(100,48,48),new Color(108,48,48),new Color(112,44,44),new Color(120,44,44),new Color(128,40,40),new Color(132,40,40),new Color(140,36,36),new Color(144,36,36),new Color(152,32,32),new Color(156,32,32),new Color(164,28,28),new Color(168,28,28),new Color(176,24,24),new Color(180,24,24),new Color(188,20,20),new Color(196,20,20),new Color(200,16,16),new Color(208,16,16),new Color(212,12,12),new Color(220,12,12),new Color(224,8,8),new Color(232,8,8),new Color(236,4,4),new Color(244,4,4),new Color(252,0,0),new Color(252,4,0),new Color(252,12,0),new Color(252,20,0),new Color(252,28,0),new Color(252,36,0),new Color(252,44,0),new Color(252,52,0),new Color(252,60,0),new Color(252,68,0),new Color(252,76,0),new Color(252,84,0),new Color(252,92,0),new Color(252,100,0),new Color(252,108,0),new Color(252,116,0),new Color(252,124,0),new Color(252,132,0),new Color(252,140,0),new Color(252,148,0),new Color(252,156,0),new Color(252,164,0),new Color(252,172,0),new Color(252,180,0),new Color(252,188,0),new Color(252,196,0),new Color(252,204,0),new Color(252,212,0),new Color(252,220,0),new Color(252,228,0),new Color(252,236,0),new Color(252,244,0),new Color(252,252,0),new Color(252,252,4),new Color(252,252,12),new Color(252,252,20),new Color(252,252,28),new Color(252,252,36),new Color(252,252,44),new Color(252,252,52),new Color(252,252,60),new Color(252,252,68),new Color(252,252,76),new Color(252,252,84),new Color(252,252,92),new Color(252,252,100),new Color(252,252,108),new Color(252,252,116),new Color(252,252,124),new Color(252,252,132),new Color(252,252,140),new Color(252,252,148),new Color(252,252,156),new Color(252,252,164),new Color(252,252,172),new Color(252,252,180),new Color(252,252,188),new Color(252,252,196),new Color(252,252,204),new Color(252,252,212),new Color(252,252,220),new Color(252,252,228),new Color(252,252,236),new Color(252,252,244),new Color(252,252,252),new Color(252,252,252),new Color(252,248,248),new Color(252,248,244),new Color(252,244,240),new Color(252,244,236),new Color(252,240,232),new Color(252,240,228),new Color(252,236,224),new Color(252,236,220),new Color(252,232,216),new Color(252,232,212),new Color(252,228,208),new Color(252,228,204),new Color(252,224,200),new Color(252,224,196),new Color(252,220,192),new Color(252,220,188),new Color(252,216,184),new Color(252,216,180),new Color(252,212,176),new Color(252,212,172),new Color(252,208,168),new Color(252,208,164),new Color(252,204,160),new Color(252,204,156),new Color(252,200,152),new Color(252,200,148),new Color(252,196,144),new Color(252,196,140),new Color(252,192,136),new Color(252,192,132),new Color(252,188,128),new Color(252,184,124),new Color(252,184,120),new Color(252,180,116),new Color(252,180,112),new Color(252,176,108),new Color(252,176,104),new Color(252,172,100),new Color(252,172,96),new Color(252,168,92),new Color(252,168,88),new Color(252,164,84),new Color(252,164,80),new Color(252,160,76),new Color(252,160,72),new Color(252,156,68),new Color(252,156,64),new Color(252,152,60),new Color(252,152,56),new Color(252,148,52),new Color(252,148,48),new Color(252,144,44),new Color(252,144,40),new Color(252,140,36),new Color(252,140,32),new Color(252,136,28),new Color(252,136,24),new Color(252,132,20),new Color(252,132,16),new Color(252,128,12),new Color(252,128,8),new Color(252,124,4),new Color(252,120,0),new Color(252,120,0),new Color(252,116,0),new Color(252,112,0),new Color(252,108,0),new Color(252,104,0),new Color(252,100,0),new Color(252,96,0),new Color(252,92,0),new Color(252,88,0),new Color(252,84,0),new Color(252,80,0),new Color(252,76,0),new Color(252,72,0),new Color(252,68,0),new Color(252,64,0),new Color(252,60,0),new Color(252,60,0),new Color(252,56,0),new Color(252,52,0),new Color(252,48,0),new Color(252,44,0),new Color(252,40,0),new Color(252,36,0),new Color(252,32,0),new Color(252,28,0),new Color(252,24,0),new Color(252,20,0),new Color(252,16,0),new Color(252,12,0),new Color(252,8,0),new Color(252,4,0),new Color(252,0,0),new Color(252,0,0),new Color(248,0,0),new Color(244,0,0),new Color(244,0,0),new Color(240,0,0),new Color(236,0,0),new Color(232,0,0),new Color(232,0,0),new Color(228,0,0),new Color(224,0,0),new Color(224,0,0),new Color(220,0,0),new Color(216,0,0),new Color(212,0,0),new Color(212,0,0),new Color(208,0,0),new Color(204,0,0),new Color(204,0,0),new Color(200,0,0),new Color(196,0,0),new Color(192,0,0),new Color(192,0,0),new Color(188,0,0),new Color(184,0,0),new Color(184,0,0),new Color(180,0,0),new Color(176,0,0),new Color(172,0,0),new Color(172,0,0),new Color(168,0,0),new Color(164,0,0),new Color(160,0,0),new Color(160,0,0),new Color(156,4,4),new Color(152,4,4),new Color(148,8,8),new Color(144,8,8),new Color(140,12,12),new Color(140,12,12),new Color(136,16,16),new Color(132,16,16),new Color(128,20,20),new Color(124,20,20),new Color(120,24,24),new Color(120,24,24),new Color(116,28,28),new Color(112,28,28),new Color(108,32,32),new Color(104,32,32),new Color(100,36,36),new Color(100,36,36),new Color(96,40,40),new Color(92,40,40),new Color(88,44,44),new Color(84,44,44),new Color(80,48,48),new Color(80,48,48),new Color(76,52,52),new Color(72,52,52),new Color(68,56,56),new Color(64,56,56),new Color(60,60,60),new Color(60,60,60)};
Color cols1[]={new Color(0,0,0),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(0,0,168),new Color(40,124,0),new Color(40,124,0),new Color(44,124,0),new Color(44,124,0),new Color(44,124,4),new Color(44,124,4),new Color(44,128,4),new Color(44,128,4),new Color(48,128,4),new Color(48,128,4),new Color(48,128,8),new Color(48,128,8),new Color(48,132,8),new Color(48,132,8),new Color(52,132,8),new Color(52,132,8),new Color(56,132,12),new Color(56,132,12),new Color(60,132,12),new Color(60,132,12),new Color(60,136,12),new Color(60,136,12),new Color(60,136,16),new Color(60,136,16),new Color(60,140,16),new Color(60,140,16),new Color(64,140,16),new Color(64,140,16),new Color(64,140,20),new Color(64,140,20),new Color(64,144,20),new Color(64,144,20),new Color(68,144,20),new Color(68,144,20),new Color(68,144,24),new Color(68,144,24),new Color(68,148,24),new Color(72,148,24),new Color(72,148,28),new Color(72,152,28),new Color(72,152,32),new Color(76,152,32),new Color(76,156,32),new Color(80,156,32),new Color(80,156,36),new Color(80,160,36),new Color(80,160,40),new Color(84,160,40),new Color(84,164,40),new Color(88,164,40),new Color(88,164,44),new Color(88,168,44),new Color(88,168,48),new Color(92,168,48),new Color(92,172,48),new Color(96,172,48),new Color(96,172,52),new Color(96,176,52),new Color(100,176,52),new Color(100,176,56),new Color(100,180,56),new Color(100,180,56),new Color(104,180,60),new Color(104,184,60),new Color(104,184,64),new Color(108,184,64),new Color(108,188,64),new Color(108,188,68),new Color(112,188,68),new Color(112,188,72),new Color(112,192,72),new Color(112,192,76),new Color(116,192,76),new Color(116,196,76),new Color(116,196,80),new Color(120,196,80),new Color(120,200,80),new Color(120,200,84),new Color(124,200,84),new Color(124,204,84),new Color(124,204,88),new Color(128,204,88),new Color(128,208,88),new Color(128,208,92),new Color(132,208,92),new Color(132,212,92),new Color(136,212,92),new Color(136,212,96),new Color(136,216,96),new Color(136,216,100),new Color(140,216,100),new Color(140,220,100),new Color(140,220,104),new Color(144,220,104),new Color(144,224,104),new Color(144,224,108),new Color(148,224,108),new Color(148,228,108),new Color(152,228,108),new Color(152,228,108),new Color(156,228,108),new Color(156,228,108),new Color(160,228,108),new Color(164,228,108),new Color(168,228,108),new Color(168,228,108),new Color(172,228,108),new Color(172,228,108),new Color(176,228,108),new Color(176,228,108),new Color(180,228,108),new Color(180,228,108),new Color(184,228,108),new Color(184,228,108),new Color(188,228,108),new Color(188,228,108),new Color(192,228,108),new Color(196,228,108),new Color(196,228,108),new Color(200,228,108),new Color(204,228,108),new Color(204,228,108),new Color(208,228,108),new Color(208,228,108),new Color(212,228,108),new Color(212,228,108),new Color(216,228,108),new Color(220,228,108),new Color(220,228,108),new Color(224,228,108),new Color(228,228,108),new Color(228,228,108),new Color(232,228,108),new Color(232,228,108),new Color(232,228,104),new Color(232,228,104),new Color(232,228,100),new Color(232,228,100),new Color(232,228,96),new Color(232,228,96),new Color(232,228,92),new Color(232,224,92),new Color(232,224,92),new Color(232,220,88),new Color(232,216,84),new Color(232,216,80),new Color(232,212,80),new Color(232,212,76),new Color(232,208,76),new Color(232,204,72),new Color(232,204,68),new Color(232,200,68),new Color(232,200,64),new Color(232,200,64),new Color(232,196,64),new Color(232,196,60),new Color(232,192,60),new Color(232,192,56),new Color(232,188,56),new Color(232,188,52),new Color(232,184,52),new Color(232,184,48),new Color(232,180,48),new Color(232,180,44),new Color(232,180,44),new Color(232,176,44),new Color(232,176,44),new Color(232,176,40),new Color(232,176,40),new Color(232,172,40),new Color(232,172,36),new Color(232,168,36),new Color(232,168,36),new Color(228,164,32),new Color(228,164,32),new Color(228,160,32),new Color(228,160,32),new Color(224,156,28),new Color(224,152,24),new Color(224,152,24),new Color(224,148,20),new Color(220,148,20),new Color(220,140,16),new Color(220,140,16),new Color(220,132,16),new Color(216,132,16),new Color(216,124,8),new Color(216,124,8),new Color(216,116,8),new Color(128,128,128),new Color(128,128,128),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(192,192,192),new Color(192,192,192),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252),new Color(252,252,252)};
int[][] terrain;
int i, j, k, q, r, s, lod, half;
double roughness=10;
double sn=Math.sin(Math.PI / 36);
double sn1=Math.sin(5*Math.PI / 12);
double cn=Math.cos(Math.PI / 36);
double cn1=Math.cos(5*Math.PI / 12);
String terra="Wireframe";
String texture="Topo";
int divisions, avg, sum;
int px[]= new int[3];
int py[]=new int[3];
public void init() {
    resize(500,300);
    offscr=createImage(500,300);
    offscrgr=offscr.getGraphics();
    create_ground();
    draw_ground();
}
public void start() {
}
public boolean mouseDown(Event e, int x, int y)
    {
    if(x>=50 & x<=150 & y>=282 & y<=295)
    {
    create_ground();
    draw_ground();
    repaint();
    }
    if(x>=405 & x<=485 & y>=277 & y<=283)
    {
    roughness=(int)Math.round((x-405)/4);
    create_ground();
    draw_ground();
    repaint();
    }
    if(x>=530-divisions & x<=490 & y>=179 & y<=191)
    {
    terra="Wireframe";   
    draw_ground();
    repaint();
    }
    if(x>=530-divisions & x<=490 & y>=159 & y<=171)
    {
    terra="Rendered";   
    draw_ground();
    repaint();
    }
    if(x>=530-divisions & x<=490 & y>=239 & y<=251)
    {
    texture="Volcano";   
    draw_ground();
    repaint();
    }
    if(x>=530-divisions & x<=490 & y>=219 & y<=231)
    {
    texture="Topo";   
    draw_ground();
    repaint();
    }

    return true;
    }
public void paint(Graphics g)
    {
        g.drawImage(offscr,0,0,this);
        g.setColor(Color.black);
        g.fillRect(1,1,490-divisions,20);
        g.fillRect(1,280,490-divisions,19);
        g.setColor(Color.red);
        g.drawRect(0,0,499,299);
        g.drawLine(1,280,499-divisions,280);
        g.drawLine(499-divisions,1,499-divisions,299);
        g.drawLine(499-divisions,divisions+1,499,divisions+1);
        g.drawLine(1,20,499-divisions,20);
        g.setColor(Color.green);
        g.drawString("Create New",50,295);
        g.setColor(Color.yellow);
        g.drawString("Fractal Landscape "+terra+" with roughness level "+roughness,15,15);
        g.drawString("Fractals Unleashed 1999",220,295);
        g.drawString("Terrain",510-divisions,150);
        if(terra=="Rendered"){
        g.setColor(Color.red);
        }
        g.drawString("Rendered",530-divisions,170);
        g.setColor(Color.yellow);
        if(terra=="Wireframe"){
        g.setColor(Color.red);
        }
        g.drawString("Wireframe",530-divisions,190);
        g.setColor(Color.yellow);
        g.drawString("Texture",510-divisions,210);
        if(texture=="Topo"){
        g.setColor(Color.red);
        }
        g.drawString("Topo",530-divisions,230);
        g.setColor(Color.yellow);
        if(texture=="Volcano"){
        g.setColor(Color.red);
        }
        g.drawString("Volcano",530-divisions,250);
        g.setColor(Color.yellow);
        g.drawString("Roughness",510-divisions,270);
        g.setColor(Color.red);
        g.drawLine(405,280,485,280);
        g.drawOval(403+(int)roughness*4,278,4,4);
    }
public void create_ground()
    {
lod=7;
divisions = 1 << lod;
terrain = new int[(divisions + 1)*2][(divisions + 1)*2];
terrain[0][0] = (int)Math.round(Math.random()*254)+1;
terrain[0][divisions] = (int)Math.round(Math.random()*254)+1;
terrain[divisions][divisions] = (int)Math.round(Math.random()*254)+1;
terrain[divisions][0] = (int)Math.round(Math.random()*254)+1;
terrain[divisions/2][divisions/2] = (int)Math.round(Math.random()*254)+1;
terrain[0][divisions/2] = (int)Math.round(Math.random()*254)+1;
terrain[divisions/2][0] = (int)Math.round(Math.random()*254)+1;
terrain[divisions][divisions/2] = (int)Math.round(Math.random()*254)+1;
terrain[divisions/2][divisions] = (int)Math.round(Math.random()*254)+1;
for (i = 0; i < lod; ++ i) {
q = 1 << i;
r = 1 << (lod - i);
s = r >> 1;
for (j = 0; j < divisions; j += r){
    for (k = 0; k < divisions; k += r){
        diamond (j, k, r, roughness);
        }
    }
if (s > 0)
    {
for (j = 0; j <= divisions; j += s){
        for (k = (j + s) % r; k <= divisions; k += r){   
        square (j - s, k - s, r, roughness);
            }
        }
    }
}
}
private void draw_ground()
{
    offscrgr.setColor(Color.black);
    offscrgr.fillRect(1,1,499,299);
    if(terra=="Rendered"){
    for (k=0; k<divisions; k++){
this.setForeground(Color.black);
this.getGraphics().fillRect(10,25,70,16);
this.setForeground(Color.red);
this.getGraphics().drawString((int)Math.round(((double)k/divisions)*100) + "% done",20,40);
this.setForeground(Color.black);
    for(i=0; i<divisions; i++){
    if(texture=="Topo"){
    offscrgr.setColor(cols1[256-((int)Math.round((terrain[i][k]+terrain[i+1][k]+terrain[i][k+1])/3))]);
    }
    else{
    offscrgr.setColor(cols[256-((int)Math.round((terrain[i][k]+terrain[i+1][k]+terrain[i][k+1])/3))]);
    }
    px[0]=80+(int)Math.round(cn * i - cn1 * k)*2;
    py[0]=70+(int)Math.round(sn * i + sn1 * k)+(int)Math.round(terrain[i][k]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    px[1]=80+(int)Math.round(cn * i - cn1 * (k+1))*2;
    py[1]=70+(int)Math.round(sn * i + sn1 * (k+1))+(int)Math.round(terrain[i][k+1]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    px[2]=80+(int)Math.round(cn * (i+1) - cn1 * k)*2;
    py[2]=70+(int)Math.round(sn * (i+1) + sn1 * k)+(int)Math.round(terrain[i+1][k]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    offscrgr.fillPolygon(px,py,3);
    if(texture=="Topo"){
    offscrgr.setColor(cols1[256-((int)Math.round((terrain[i+1][k]+terrain[i+1][k+1]+terrain[i][k+1])/3))]);
    }
    else{
    offscrgr.setColor(cols[256-((int)Math.round((terrain[i+1][k]+terrain[i+1][k+1]+terrain[i][k+1])/3))]);
    }
    px[0]=80+(int)Math.round(cn * (i+1) - cn1 * k)*2;
    py[0]=70+(int)Math.round(sn * (i+1) + sn1 * k)+(int)Math.round(terrain[i+1][k]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    px[1]=80+(int)Math.round(cn * i - cn1 * (k+1))*2;
    py[1]=70+(int)Math.round(sn * i + sn1 * (k+1))+(int)Math.round(terrain[i][k+1]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    px[2]=80+(int)Math.round(cn * (i+1) - cn1 * (k+1))*2;
    py[2]=70+(int)Math.round(sn * (i+1) + sn1 * (k+1))+(int)Math.round(terrain[i+1][k+1]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    offscrgr.fillPolygon(px,py,3);
    offscrgr.drawLine(499-divisions+i,k+1,499-divisions+i,k+1);
        }
        }
    }
    else{
    for (k=0; k<divisions; k=k+4){
    for(i=0; i<divisions; i=i+4){
    if(texture=="Topo"){
    offscrgr.setColor(cols1[256-((int)Math.round((terrain[i][k]+terrain[i+1][k]+terrain[i][k+1])/3))]);
    }
    else{
    offscrgr.setColor(cols[256-((int)Math.round((terrain[i][k]+terrain[i+1][k]+terrain[i][k+1])/3))]);
    }
    px[0]=80+(int)Math.round(cn * i - cn1 * k)*2;
    py[0]=70+(int)Math.round(sn * i + sn1 * k)+(int)Math.round(terrain[i][k]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    px[1]=80+(int)Math.round(cn * i - cn1 * (k+4))*2;
    py[1]=70+(int)Math.round(sn * i + sn1 * (k+4))+(int)Math.round(terrain[i][k+4]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    px[2]=80+(int)Math.round(cn * (i+4) - cn1 * (k))*2;
    py[2]=70+(int)Math.round(sn * (i+4) + sn1 * (k))+(int)Math.round(terrain[i+4][k]/2-64-(terrain[divisions/2][divisions/2]/2-70));
    offscrgr.drawLine(px[0],py[0],px[1],py[1]);
    offscrgr.drawLine(px[0],py[0],px[2],py[2]);
        }
        }
    for (k=0; k<divisions; k++){
this.setForeground(Color.black);
this.getGraphics().fillRect(10,25,70,16);
this.setForeground(Color.red);
this.getGraphics().drawString((int)Math.round(((double)k/divisions)*100) + "% done",20,40);
this.setForeground(Color.black);
    for(i=0; i<divisions; i++){
    if(texture=="Topo"){
    offscrgr.setColor(cols1[256-((int)Math.round((terrain[i][k]+terrain[i+1][k]+terrain[i][k+1])/3))]);
    }
    else{
    offscrgr.setColor(cols[256-((int)Math.round((terrain[i][k]+terrain[i+1][k]+terrain[i][k+1])/3))]);
    }
    offscrgr.drawLine(499-divisions+i,k+1,499-divisions+i,k+1);
        }
        }
    }
}
private void diamond (int x, int y, int side, double scale) {
if (side > 1) {
half = side / 2;
avg = (int)Math.round((terrain[x][y] + terrain[x + side][y] +
terrain[x + side][y + side] + terrain[x][y + side]) * 0.25);
    if(terrain[x + half][y + half]==0)
    {
terrain[x + half][y + half] = avg + (int)Math.round(Math.random() * scale - scale / 2);
    }
}
}
private void square (int x, int y, int side, double scale) {
half = side / 2;
avg = 0;
sum = 0;
if (x >= 0)
{ avg += terrain[x][y + half]; sum += 1; }
if (y >= 0)
{ avg += terrain[x + half][y]; sum += 1; }
if (x + side <= divisions)
{ avg += terrain[x + side][y + half]; sum += 1; }
if (y + side <= divisions)
{ avg += terrain[x + half][y + side]; sum += 1; }
    if(terrain[x + half][y + half]==0)
        {
        terrain[x + half][y + half] = avg / sum + (int)Math.round(Math.random() * scale-scale/2);
        }
    }
}

forward