1 /* subdiv1.c - subdivision algorithm #1:  cross / diamond
2  *
3  * Copyright (C) 2001 Patrice St-Gelais
4  *         patrstg@users.sourceforge.net
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 #include "subdiv1.h"
22 
subdiv1_opt_new()23 subdiv1_opt *subdiv1_opt_new() {
24 	subdiv1_opt *opt;
25 // printf("SUBDIV1_OPT_NEW\n");
26 	opt = (subdiv1_opt *) x_malloc(sizeof(subdiv1_opt), "subdiv2_opt");
27 	opt->seed = DEFAULT_SEED;
28 	opt->roughness = 0;
29 	opt->top_random = TRUE;
30 	opt->top_value = 0xF000;
31 	opt->frq_control_mask = 0;
32 	return opt;
33 }
34 
re_calc(hf_type val,hf_type * a,hf_type * b,hf_type * c,hf_type * d,int c_level)35 void re_calc( hf_type val, hf_type *a, hf_type *b,
36 		hf_type *c, hf_type *d, int c_level)
37 {
38 	int lag;
39 //	static float p1 = 0.9, p2 = 0.1;
40 	if (!IF_RECALC) return;
41 
42 	// Rough at small scales with lag constant at 3
43 //	lag = MIN(1,c_level-8); // rough at high scales, high frq (low scale) quite smooth
44 				// must activate re_calc for all points,
45 				// otherwise the "calculation flow" is visible
46 //	lag = MIN(0,4-c_level); // high frq smooth, low frq rough
47 	lag = MAX(1,MIN(7,8-c_level)); // Best, better with level_factor = 1
48 //	lag = MAX(1,(8-c_level) >> 1); // Not bad with level_factor = 1
49 //... last one gives visible crests when painting
50 	val = val >> lag;
51 	*(a) = val + ((*a)-((*a)>>lag));
52 	*(b) = val + ((*b)-((*b)>>lag));
53 	*(c) = val + ((*c)-((*c)>>lag));
54 	*(d) = val + ((*d)-((*d)>>lag));
55 }
56 
calc_midx_midy(hf_type * hf_buf,int max_x,int max_y,int x0,int y0,int x1,int y1,int c_level,subdiv1_opt * opt)57 void calc_midx_midy(hf_type *hf_buf, int max_x, int max_y, int x0, int y0, int x1, int y1, int c_level, subdiv1_opt *opt) {
58 
59 	int mid_x, mid_y, r;
60 	hf_type avrg, val;
61 	mid_x = (x0 + x1)>>1;
62 	mid_y = (y0 + y1)>>1;
63 
64 	avrg = calc_avrg (
65 		*(hf_buf + (y0*max_x) + x0),
66 		*(hf_buf +( (y1%max_y) * max_x) +x0),
67 		*(hf_buf + (y0*max_x) + (x1%max_x) ),
68 		*(hf_buf +( (y1%max_y) * max_x) + (x1%max_x) ));
69 
70 	// mid_x, mid_y
71 
72 	if ((!opt->top_random) && (c_level == 0)) {
73 		*(hf_buf+(mid_y*max_x)+mid_x) = opt->top_value;
74 	  }
75 	else {
76 
77 //		r = (hf_type) ( ((hf_type) rand()) /
78 //			 pow(2.282,(double) c_level - opt->roughness - 1 ) ) ;
79 
80 		r = (hf_type) ( ((hf_type) rand()) >>
81 		 MAX(MINLAG,(MIN(MAXLAG,c_level - opt->roughness - 1))) );
82 
83 		val = avrg OP_HF r;
84 		*(hf_buf+(mid_y*max_x)+mid_x) = val;
85 
86 		// Some smoothing
87 
88 		   re_calc(val,
89 			hf_buf + (y0*max_x) + x0,
90 			hf_buf +( (y1%max_y) * max_x) +x0,
91 			hf_buf + (y0*max_x) + (x1%max_x) ,
92 			hf_buf +( (y1%max_y) * max_x) + (x1%max_x),c_level);
93 	}
94 }
95 
calc_x_y(hf_type * hf_buf,int max_x,int max_y,int x0,int y0,int x1,int y1,int c_level,subdiv1_opt * opt)96 void calc_x_y(	hf_type *hf_buf, int max_x, int max_y,
97 		int x0, int y0, int x1, int y1,
98 		int c_level,
99 		subdiv1_opt *opt)
100 {
101 	int mid_x, mid_y, x_1, y_1;
102 	hf_type avrg, r, val;
103 
104 	mid_x = (x0 + x1)>>1;
105 	mid_y = (y0 + y1)>>1;
106 
107 	// Initialize height values - avrg taken from cross pos.
108 	x_1 = x0 - (mid_x - x0);
109 	if (x_1 < 0)
110 		x_1 = max_x + x_1;
111 	y_1 = mid_y - (y1 - y0);
112 	if (y_1 < 0)
113 		y_1 = max_y + y_1;
114 	x1 = x1%max_x;
115 	y1 = y1%max_y;
116 	// All points averaged from the mid points of the same level
117 	// All extremities are present, so we divide by 4 (>>2)
118 
119 	// For x, mid_y
120 	avrg = calc_avrg (*(hf_buf +( y1 * max_x) + x0),
121 		*(hf_buf +( mid_y * max_x) + mid_x),
122 		*(hf_buf + (y0 * max_x) + x0),
123 		*(hf_buf +( mid_y * max_x) + x_1 ));
124 
125 	r = (hf_type) ( ((hf_type) rand()) >>
126 		MAX(MINLAG,(MIN(MAXLAG,c_level - opt->roughness - 1))) );
127 	// x0, mid_y
128 
129 	val =	avrg OP_HF r;
130 
131 	*(hf_buf+(mid_y*max_x) + x0) = val;
132 
133 	// Some smoothing
134 	if (IF_RECALC2)
135 		re_calc(val,hf_buf +( y1 * max_x) + x0,
136 			hf_buf +( mid_y * max_x) + mid_x,
137 			hf_buf + (y0 * max_x) + x0,
138 			hf_buf +( mid_y * max_x) + x_1, c_level );
139 
140 
141 	// For mid_x, y
142 	avrg = calc_avrg
143 		(*(hf_buf +( y_1 * max_x) + mid_x),
144 		*(hf_buf +( y0 * max_x) + x0),
145 		*(hf_buf + (y0 * max_x) + x1),
146 		*(hf_buf +( mid_y * max_x) + mid_x ));
147 
148 	// mid_x, y0
149 	r = (hf_type) ( ((hf_type) rand()) >>
150 		MAX(MINLAG,(MIN(MAXLAG,c_level - opt->roughness - 1))) );
151 
152 	val = avrg OP_HF r;
153 
154 	*(hf_buf+(y0*max_x) + mid_x) = val;
155 
156 	// Some moothing
157 	if (IF_RECALC2)
158 		re_calc(val,
159 			hf_buf +( y_1 * max_x) + mid_x,
160 			hf_buf +( y0 * max_x) + x0,
161 			hf_buf + (y0 * max_x) + x1,
162 			hf_buf + ( mid_y * max_x) + mid_x, c_level );
163 
164 }
165 
calc_level(hf_type * hf_buf,int max_x,int max_y,int level,subdiv1_opt * opt)166 void calc_level(hf_type *hf_buf, int max_x, int max_y, int level, subdiv1_opt *opt) {
167 	int chunk, i, j;
168 	chunk = max_x >> level; // Works only for squares
169 
170 	for (i = 0; i < max_x; i= i+chunk) // diamond
171 		for (j = 0; j < max_x; j = j + chunk)
172 			calc_midx_midy(hf_buf, max_x, max_y, 0 + i, 0 + j, i+chunk, j+chunk, level, opt);
173 	for (i = 0; i < max_x; i= i+chunk) // cross
174 		for (j = 0; j < max_x; j = j + chunk)
175 			calc_x_y(hf_buf, max_x, max_y, 0+i, 0+j, i+chunk, j+chunk,
176 				level, opt);
177 }
178 
calc_subdiv1(hf_type * hf_buf,int max_x,int max_y,subdiv1_opt * opt)179 void calc_subdiv1 (hf_type *hf_buf, int max_x, int max_y, subdiv1_opt *opt) {
180 
181 	int i, levels;
182 	srand(opt->seed);
183 
184 	*(hf_buf) = (hf_type) rand() ;
185 
186 	levels = log2i(max_x);
187 	for (i=0; i< levels; i++) {
188 		calc_level(hf_buf, max_x, max_y, i, opt);
189 	}
190 
191 }
192 
subdiv1(hf_struct_type * hf,subdiv1_opt * opt)193 void subdiv1(hf_struct_type *hf, subdiv1_opt *opt) {
194 	// Plasma - style subdivision
195 	// Non recursive algorithm
196 	// For the given level:
197 	// 1. Calculate values for all mid points
198 	//	Average: square
199 	// 2. Calculate values for all mid_x, y0
200 	// 3. Calculate values for x0, mid_y_
201 // printf("SUBDIV1\n");
202 //	There could have been a size change, so we reallocate the memory
203 
204 	hf->hf_buf = (hf_type *) x_realloc(hf->hf_buf, hf->max_x * hf->max_y * sizeof(hf_type), "hf_type (hf_buf in subdiv1)");
205 
206 	calc_subdiv1 (hf->hf_buf, hf->max_x, hf->max_y, opt);
207 }
208 
209 
210