1 //Copyright Paul Reiche, Fred Ford. 1992-2002
2 
3 /*
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 // See doc/devel/planettopo for details.
20 
21 #include "libs/gfxlib.h"
22 #include "libs/mathlib.h"
23 #include "planets.h"
24 
25 void
DeltaTopography(COUNT num_iterations,SBYTE * DepthArray,RECT * pRect,SIZE depth_delta)26 DeltaTopography (COUNT num_iterations, SBYTE *DepthArray, RECT *pRect,
27 		SIZE depth_delta)
28 {
29 	SIZE width, height, delta_y;
30 	struct
31 	{
32 		COORD x_top, x_bot;
33 		SIZE x_incr, delta_x, error_term;
34 	} LineDDA0, LineDDA1;
35 
36 	width = pRect->extent.width;
37 	height = pRect->extent.height;
38 	delta_y = (height - 1) << 1;
39 	do
40 	{
41 		SIZE d;
42 		COUNT h, w1, w2;
43 		DWORD rand_val;
44 		SBYTE *lpDst;
45 
46 		if ((RandomContext_Random (SysGenRNG) & 1) == 0)
47 			depth_delta = -depth_delta;
48 
49 		rand_val = RandomContext_Random (SysGenRNG);
50 		w1 = LOWORD (rand_val);
51 		w2 = HIWORD (rand_val);
52 
53 		LineDDA0.x_top = LOBYTE (w1) % width;
54 		LineDDA0.x_bot = HIBYTE (w1) % width;
55 		LineDDA0.delta_x = (LineDDA0.x_bot - LineDDA0.x_top) << 1;
56 		if (LineDDA0.delta_x >= 0)
57 			LineDDA0.x_incr = 1;
58 		else
59 		{
60 			LineDDA0.x_incr = -1;
61 			LineDDA0.delta_x = -LineDDA0.delta_x;
62 		}
63 		if (LineDDA0.delta_x > delta_y)
64 			LineDDA0.error_term = -(LineDDA0.delta_x >> 1);
65 		else
66 			LineDDA0.error_term = -(delta_y >> 1);
67 
68 		LineDDA1.x_top = (LOBYTE (w2) % (width - 1)) + LineDDA0.x_top + 1;
69 		LineDDA1.x_bot = (HIBYTE (w2) % (width - 1)) + LineDDA0.x_bot + 1;
70 		LineDDA1.delta_x = (LineDDA1.x_bot - LineDDA1.x_top) << 1;
71 		if (LineDDA1.delta_x >= 0)
72 			LineDDA1.x_incr = 1;
73 		else
74 		{
75 			LineDDA1.x_incr = -1;
76 			LineDDA1.delta_x = -LineDDA1.delta_x;
77 		}
78 		if (LineDDA1.delta_x > delta_y)
79 			LineDDA1.error_term = -(LineDDA1.delta_x >> 1);
80 		else
81 			LineDDA1.error_term = -(delta_y >> 1);
82 
83 		lpDst = &DepthArray[LineDDA0.x_top];
84 		h = height;
85 		do
86 		{
87 			COUNT w;
88 
89 			w1 = LineDDA1.x_top - LineDDA0.x_top;
90 			w2 = width - w1;
91 
92 			if ((int)(LineDDA0.x_top + w1) > (int)width)
93 				w = width - LineDDA0.x_top;
94 			else
95 			{
96 				w = w1;
97 				LineDDA0.x_top += w1;
98 			}
99 			w1 -= w;
100 			while (w--)
101 			{
102 				d = *lpDst + depth_delta;
103 				if (d >= -128 && d <= 127)
104 					*lpDst = (SBYTE)d;
105 				++lpDst;
106 			}
107 			if (w1 == 0)
108 			{
109 				if (LineDDA0.x_top == width)
110 				{
111 					LineDDA0.x_top = 0;
112 					lpDst -= width;
113 				}
114 			}
115 			else
116 			{
117 				LineDDA0.x_top = w1;
118 				lpDst -= width;
119 				do
120 				{
121 					d = *lpDst + depth_delta;
122 					if (d >= -128 && d <= 127)
123 						*lpDst = (SBYTE)d;
124 					++lpDst;
125 				} while (--w1);
126 			}
127 
128 			if ((int)(LineDDA0.x_top + w2) > (int)width)
129 				w = width - LineDDA0.x_top;
130 			else
131 			{
132 				w = w2;
133 				LineDDA0.x_top += w2;
134 			}
135 			w2 -= w;
136 			while (w--)
137 			{
138 				d = *lpDst - depth_delta;
139 				if (d >= -128 && d <= 127)
140 					*lpDst = (SBYTE)d;
141 				++lpDst;
142 			}
143 			if (w2 == 0)
144 			{
145 				if (LineDDA0.x_top == width)
146 				{
147 					LineDDA0.x_top = 0;
148 					lpDst -= width;
149 				}
150 			}
151 			else
152 			{
153 				LineDDA0.x_top = w2;
154 				lpDst -= width;
155 				do
156 				{
157 					d = *lpDst - depth_delta;
158 					if (d >= -128 && d <= 127)
159 						*lpDst = (SBYTE)d;
160 					++lpDst;
161 				} while (--w2);
162 			}
163 
164 			lpDst += pRect->extent.width;
165 
166 			if (delta_y >= LineDDA0.delta_x)
167 			{
168 				if ((LineDDA0.error_term += LineDDA0.delta_x) >= 0)
169 				{
170 					lpDst += LineDDA0.x_incr;
171 					LineDDA0.x_top += LineDDA0.x_incr;
172 					LineDDA0.error_term -= delta_y;
173 				}
174 			}
175 			else
176 			{
177 				do
178 				{
179 					lpDst += LineDDA0.x_incr;
180 					LineDDA0.x_top += LineDDA0.x_incr;
181 				} while ((LineDDA0.error_term += delta_y) < 0);
182 				LineDDA0.error_term -= LineDDA0.delta_x;
183 			}
184 
185 			if (delta_y >= LineDDA1.delta_x)
186 			{
187 				if ((LineDDA1.error_term += LineDDA1.delta_x) >= 0)
188 				{
189 					LineDDA1.x_top += LineDDA1.x_incr;
190 					LineDDA1.error_term -= delta_y;
191 				}
192 			}
193 			else
194 			{
195 				do
196 				{
197 					LineDDA1.x_top += LineDDA1.x_incr;
198 				} while ((LineDDA1.error_term += delta_y) < 0);
199 				LineDDA1.error_term -= LineDDA1.delta_x;
200 			}
201 		} while (--h);
202 	} while (--num_iterations);
203 }
204 
205 
206 
207