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