Guest User

Untitled

a guest
Feb 19th, 2018
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.28 KB | None | 0 0
  1. import java.applet.*;
  2. import java.util.*;
  3. import java.io.*;
  4. import java.net.*;
  5. import java.awt.*;
  6. import java.awt.image.ColorModel;
  7. import java.awt.image.MemoryImageSource;
  8.  
  9. /* portions of this code were adapted from the DitherTest applet */
  10. /* midpoint subdivision codes adapted from Usenet and published references
  11. * - Basic plasma from implementation by Andrea Griffini (Usenet)
  12. * - Diamond-square subdivision adapted from implementation by
  13. * Paul Martz (Usenet)
  14. * - Offset-squares method adapted from 'moonbase' demo by James McNeill
  15. */
  16.  
  17. public class SubdivApplet extends Applet implements Runnable
  18. {
  19. /************************************************************
  20. * Boilerplate methods to handle painting and initialization
  21. ************************************************************/
  22.  
  23. private int width = 256;
  24. private int height = 256;
  25. private double scalefactor = 1.0;
  26. /* Frame only used for standalone apps
  27. private static Frame my_frame = null;
  28. */
  29. private int[][] heightfield;
  30. private Random rgen;
  31. private Image img;
  32. private boolean started;
  33.  
  34. /* only things done in here are done for standalone program, not applet
  35. public SubdivApplet()
  36. {
  37. setTitle("Midpoint Subdivision Fractal");
  38. }
  39. */
  40. public boolean handleEvent(Event evt)
  41. {
  42. if (evt.id == Event.WINDOW_DESTROY) System.exit(0);
  43. return super.handleEvent(evt);
  44. }
  45. public boolean action( Event evt, Object arg)
  46. {
  47. return true;
  48. }
  49. /*static*/ String calcString = "Calculating...";
  50. /*static*/ String calcMethod;
  51. public void paint(Graphics g)
  52. {
  53. int w = size().width;
  54. int h = size().height;
  55. if (img == null) {
  56. super.paint(g);
  57. g.setColor(Color.black);
  58. FontMetrics fm = g.getFontMetrics();
  59. int x = (w - fm.stringWidth(calcString))/2;
  60. int y = h/2;
  61. g.drawString(calcString, x, y);
  62. } else {
  63. g.drawImage(img, 0, 0, w, h, this);
  64. }
  65. }
  66. public void init()
  67. {
  68. int w = Integer.parseInt(getParameter("width"));
  69. if (w < =0 || w > 256) w=width;
  70. width=w;
  71. height=w;
  72. scalefactor = 256/width;
  73. calcMethod=getParameter("method");
  74. rgen = new Random();
  75. started = false;
  76. start();
  77. }
  78. /* main is used for a standalone program, not applet
  79. public static void main(String args[])
  80. {
  81. SubdivApplet f = new SubdivApplet();
  82. f.resize(width, height);
  83. f.show();
  84. my_frame = f;
  85. rgen = new Random();
  86. f.start();
  87. }
  88. */
  89. synchronized void BuildImage()
  90. {
  91. /* build the image for display -- greyscale */
  92. int pixels[];
  93. int i, j, a, index = 0, min, max;
  94. // calculate range of values in heightfield
  95. min = heightfield[0][0];
  96. max = heightfield[0][0];
  97. for (i=0;i < width;i++)
  98. {
  99. for (j=0;j < width;j++)
  100. {
  101. if (heightfield[i][j] < min) min = heightfield[i][j];
  102. if (heightfield[i][j] > max) max = heightfield[i][j];
  103. }
  104. }
  105. scalefactor = 255 / (max-min);
  106. pixels = new int[width * height];
  107. for (i=0;i < width;i++)
  108. {
  109. for (j=0;j < width;j++)
  110. {
  111. a = (int)((heightfield[i][j] - min) * scalefactor);
  112. if (a < 0) a=0;
  113. if (a > 255) a=255;
  114. /*if (a > 255) a=255;*/
  115. pixels[index++] = (255 << 24) | (a << 16) | (a << 8) | a;
  116. }
  117. }
  118.  
  119. img = createImage(new MemoryImageSource(width, height,
  120. ColorModel.getRGBdefault(),
  121. pixels, 0, width));
  122. repaint();
  123. }
  124.  
  125. /************************************************************
  126. * Thread methods to handle processing in the background
  127. ************************************************************/
  128.  
  129. Thread kicker;
  130.  
  131. public /*synchronized*/ void start() {
  132. if (!started) {
  133. started = true;
  134. kicker = new Thread(this);
  135. kicker.start();
  136. } else if ((kicker != null) && (kicker.isAlive()))
  137. kicker.resume();
  138. }
  139.  
  140. public /*synchronized*/ void stop() {
  141. try {
  142. if ((kicker != null) && (kicker.isAlive())) {
  143. kicker.suspend();
  144. }
  145. } catch (Exception e) {
  146. }
  147. }
  148.  
  149. public void restart() {
  150. try {
  151. if (kicker != null) {
  152. kicker.stop();
  153. }
  154. } catch (Exception e) {
  155. }
  156. kicker = null;
  157. img = null;
  158. started = false;
  159. start();
  160. }
  161.  
  162. public void run()
  163. {
  164. Thread me = Thread.currentThread();
  165. me.setPriority(4);
  166. if (calcMethod.equals("standard"))
  167. DoPlasma(0.5, 0);
  168. else if (calcMethod.equals("diamond-square"))
  169. DoDiamondSquare(width);
  170. else if (calcMethod.equals("offset-square"))
  171. DoOffsetSquare(width);
  172. }
  173.  
  174. /************************************************************
  175. * Plasma implementations
  176. ************************************************************/
  177.  
  178. /*
  179. Plasma example - basic midpoint subdivision on a grid
  180. grid size is a power of 2 (width for this example)
  181. integer math is used where possible
  182. random distribution is uniform random
  183.  
  184. K is scaling factor (ratio of altitude variation to length),
  185. H is constant noise factor, independent of area size;
  186.  
  187. typical values passed in are (0.5, 0.0) so that, with a width cell
  188. grid, starting values range from -128..128. This still runs the
  189. risk of overflow, but can still be acceptable.
  190.  
  191. altitude at each level is uniform random, + or - (h*K+H)/2
  192. where h is the stepsize (length of area side)
  193. */
  194.  
  195. /* this used to return 'byte' instead of 'int' */
  196. private int Rand1(int base,int delta)
  197. { int i;
  198. i=base+(rgen.nextInt()%delta)-(delta/2);
  199. /*if (i < -128) i=-128; if (i > 127) i=127;*/
  200. return (int)i;
  201. }
  202.  
  203. synchronized void DoPlasma(double K,double H)
  204. {
  205. int i,j,i2,j2,i3,j3,h,h2,delta,a,b,c,d;
  206.  
  207. /* Get the memory (widthxwidth bytes) */
  208. heightfield = new int[width][width];
  209. /* base value = 0, byte values are -128..127 */
  210. for (i=0;i < width;i++) for (j=0;j < width;j++) heightfield[i][j]=0;
  211.  
  212. /* Plasma clouds computing */
  213. for (h=width; h > 1; h=h2)
  214. {
  215. h2=h/2;
  216. delta= (int)(h*K+H);
  217. for (i=0; i < width; i+=h)
  218. { i2=((i+h)&(width-1));
  219. for (j=0; j < width; j+=h)
  220. { /* Get corner heights (a=TL, b=TR, c=BL, d=BR) */
  221. j2=((j+h)&(width-1));
  222. i3=i+h2; j3=j+h2;
  223. a=heightfield[i][j]; b=heightfield[i2][j];
  224. c=heightfield[i][j2]; d=heightfield[i2][j2];
  225.  
  226. /* Central point */
  227. heightfield[i3][j3]=Rand1((a+b+c+d)/4,delta);
  228.  
  229. /* Top point (only needed for top row) */
  230. if (i==0)
  231. heightfield[i3][j]=Rand1((a+b)/2,delta);
  232.  
  233. /* Left point (only needed for left column) */
  234. if (j==0)
  235. heightfield[i][j3]=Rand1((a+c)/2,delta);
  236.  
  237. /* Right point */
  238. heightfield[i2][j3]=Rand1((b+d)/2,delta);
  239.  
  240. /* Bottom point */
  241. heightfield[i3][j2]=Rand1((c+d)/2,delta);
  242. }
  243. }
  244. }
  245. BuildImage();
  246. }
  247. /****************************************************************
  248.  
  249. Plasma example - diamond-square midpoint subdivision on a grid.
  250.  
  251. The surface is iteratively computed by calculating the center point of
  252. the initial square (where the four corners of the surface are the
  253. corners of the square), then of the resulting diamonds, then of
  254. squares again, etc.
  255.  
  256. Code adapted from 'fillSurf' example posted to Usenet by
  257. Paul Martz (pmartz@dsd.es.com). Original source calculated
  258. full 3D points; I have elided that for this version because the
  259. underlying regular grid gives you that implicitly.
  260.  
  261. Original copyright notice:
  262. Use this code anyway you want as long as you don't sell it for
  263. money.
  264. Paul Martz, 1995
  265.  
  266. ****************************************************************/
  267.  
  268. private int avgyvals (int i, int j, int strut, int dim)
  269. {
  270. if (i == 0)
  271. return ((heightfield[i][(j-strut)&(width-1)] +
  272. heightfield[i][(j+strut)&(width-1)] +
  273. heightfield[(i+strut)&(width-1)][j]) / 3);
  274. else if (i == dim-1)
  275. return ((heightfield[i][(j-strut)&(width-1)] +
  276. heightfield[i][(j+strut)&(width-1)] +
  277. heightfield[(i-strut)&(width-1)][j]) / 3);
  278. else if (j == 0)
  279. return ((heightfield[(i-strut)&(width-1)][j] +
  280. heightfield[(i+strut)&(width-1)][j] +
  281. heightfield[i][(j+strut)&(width-1)]) / 3);
  282. else if (j == dim-1)
  283. return ((heightfield[(i-strut)&(width-1)][j] +
  284. heightfield[(i+strut)&(width-1)][j] +
  285. heightfield[i][(j-strut)&(width-1)]) / 3);
  286. else
  287. return ((heightfield[(i-strut)&(width-1)][j] +
  288. heightfield[(i+strut)&(width-1)][j] +
  289. heightfield[i][(j-strut)&(width-1)] +
  290. heightfield[i][(j+strut)&(width-1)]) / 4);
  291. }
  292.  
  293. private int avgyvals2 (int i, int j, int strut, int dim)
  294. {
  295. int tstrut = strut/2;
  296.  
  297.  
  298. return ((heightfield[(i-tstrut)&(width-1)][(j-tstrut)&(width-1)] +
  299. heightfield[(i-tstrut)&(width-1)][(j+tstrut)&(width-1)] +
  300. heightfield[(i+tstrut)&(width-1)][(j-tstrut)&(width-1)] +
  301. heightfield[(i+tstrut)&(width-1)][(j+tstrut)&(width-1)]) / 4);
  302. }
  303.  
  304. synchronized void DoDiamondSquare(int dim)
  305. {
  306. int i, j;
  307. int strut, tstrut;
  308. boolean oddline;
  309.  
  310. /* Get the memory (widthxwidth bytes) */
  311. heightfield = new int[width][width];
  312. /* base value = 0, byte values are -128..127 */
  313. for (i=0;i < width;i++) for (j=0;j < width;j++) heightfield[i][j]=0;
  314.  
  315. /* initialize things */
  316. strut = dim / 2;
  317.  
  318. /* seed the first y values */
  319. /* we disregard this for direct comparison with other method.
  320. oddline = false;
  321. for (i=0; i < dim; i+=strut)
  322. {
  323. oddline = (!oddline);
  324. for (j=0; j < dim; j+=strut)
  325. {
  326. if (!oddline) j+= strut;
  327. heightfield[i][j] = Rand1(0, strut);
  328. j+=strut;
  329. }
  330. }
  331. */
  332.  
  333. /* create fractal surface from seeded values */
  334. tstrut = strut;
  335. while (tstrut > 0)
  336. {
  337. oddline = false;
  338. for (i=0; i < dim; i+=tstrut)
  339. {
  340. oddline = (!oddline);
  341. for (j=0; j < dim; j+=tstrut)
  342. {
  343. if ((oddline) && (j==0)) j+=tstrut;
  344. heightfield[i][j] =
  345. Rand1(avgyvals (i, j, tstrut, dim), tstrut);
  346. j+=tstrut;
  347. }
  348. }
  349. if (tstrut/2 != 0)
  350. {
  351. for (i=tstrut/2; i < dim; i+=tstrut)
  352. {
  353. for (j=tstrut/2; j < dim; j+=tstrut)
  354. {
  355. heightfield[i][j] =
  356. Rand1(avgyvals2(i, j, tstrut, dim), tstrut);
  357. }
  358. }
  359. }
  360. tstrut /= 2;
  361. }
  362. BuildImage();
  363. }
  364.  
  365. /****************************************************************
  366.  
  367. Plasma example - offset square midpoint subdivision on a grid.
  368.  
  369. This method is similar to standard subdivision, but it is 'offset'
  370. in that the new points at each level are offset from the previous
  371. level by half the square size. The original corner points at level
  372. x are only used once to form a weighted average, and then become the
  373. center points of the new squares:
  374.  
  375. O O
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384. O O
  385.  
  386. becomes
  387.  
  388. x x
  389.  
  390.  
  391. O O
  392.  
  393. x x x x
  394.  
  395.  
  396.  
  397.  
  398. x x x x
  399.  
  400. O O
  401.  
  402.  
  403. x x
  404.  
  405. (Okay, so I don't do good ASCII squares; I hope you get the idea.)
  406. It should be clear that this method includes some non-local context
  407. when calculating new heights. With standard subdivision, the only
  408. heights that can ever influence the area inside the original square
  409. are the original corner points. With offset squares, most of the
  410. new corner points lie outside the original square and therefore
  411. are influenced by more distant points. This feature can be a problem,
  412. because if you don't want the map to be toroidal (wrapped in both
  413. x and y), you need to generate a large number of points outside the
  414. final terrain area. For this example, I just wrap x and y.
  415.  
  416. Original copyright notice:
  417. This code was inspired by looking at Tim Clark's (?) Mars demo; hence the name
  418. "Moonbase". (Moonbase is also the name of our student-run Linux server.)
  419. I believe the Mars demo is still available on x2ftp.oulu.fi. You are free
  420. to use my code, my ideas, whatever. I have benefited enormously from the free
  421. information on the Internet, and I would like to keep that process going.
  422. James McNeill
  423. mcneja@wwc.edu
  424.  
  425. ****************************************************************/
  426.  
  427. synchronized void DoOffsetSquare(int width)
  428. {
  429. int row_offset = 0; // start at zero for first row
  430.  
  431. /* Get the memory (widthxwidth bytes) */
  432. heightfield = new int[width][width];
  433. /* base value = 0, byte values are -128..127 */
  434. for (int i=0;i < width;i++) for (int j=0;j < width;j++) heightfield[i][j]=0;
  435.  
  436. for ( int square_size = width; square_size > 1; square_size /= 2 )
  437. {
  438. int random_range = square_size;
  439.  
  440. for ( int x1 = row_offset; x1 < width; x1 += square_size )
  441. {
  442. for ( int y1 = row_offset; y1 < width; y1 += square_size )
  443. {
  444. // Get the four corner points.
  445.  
  446. int x2 = (x1 + square_size) % width;
  447. int y2 = (y1 + square_size) % width;
  448.  
  449. int i1 = heightfield[x1][y1];
  450. int i2 = heightfield[x2][y1];
  451. int i3 = heightfield[x1][y2];
  452. int i4 = heightfield[x2][y2];
  453.  
  454. // Obtain new points by averaging the corner points.
  455.  
  456. int p1 = ((i1 * 9) + (i2 * 3) + (i3 * 3) + (i4)) / 16;
  457. int p2 = ((i1 * 3) + (i2 * 9) + (i3) + (i4 * 3)) / 16;
  458. int p3 = ((i1 * 3) + (i2) + (i3 * 9) + (i4 * 3)) / 16;
  459. int p4 = ((i1) + (i2 * 3) + (i3 * 3) + (i4 * 9)) / 16;
  460.  
  461. // Add a random offset to each new point.
  462.  
  463. p1 = Rand1(p1, random_range);
  464. p2 = Rand1(p2, random_range);
  465. p3 = Rand1(p3, random_range);
  466. p4 = Rand1(p4, random_range);
  467.  
  468. // Write out the generated points.
  469.  
  470. int x3 = (x1 + square_size/4) % width;
  471. int y3 = (y1 + square_size/4) % width;
  472. x2 = (x3 + square_size/2) % width;
  473. y2 = (y3 + square_size/2) % width;
  474.  
  475. heightfield [x3][y3] = p1;
  476. heightfield [x2][y3] = p2;
  477. heightfield [x3][y2] = p3;
  478. heightfield [x2][y2] = p4;
  479. }
  480. }
  481. row_offset = square_size/4; // set offset for next row
  482. }
  483. BuildImage();
  484. }
  485. }
Add Comment
Please, Sign In to add comment