avoid assignments between sbyte * and char *, ubyte * and char * to fix warnings...
[btb/d2x.git] / main / editor / ksegsize.c
1 /* $Id: ksegsize.c,v 1.4 2005-07-25 04:09:40 chris Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Functions for sizing segments
18  *
19  */
20
21 #ifdef RCS
22 static char rcsid[] = "$Id: ksegsize.c,v 1.4 2005-07-25 04:09:40 chris Exp $";
23 #endif
24
25 #ifdef HAVE_CONFIG_H
26 #include "conf.h"
27 #endif
28
29 #include <stdlib.h>
30
31 #include "inferno.h"
32 #include "editor.h"
33 #include "mono.h"
34 #include "error.h"
35 #include "segment.h"
36 #include "gameseg.h"
37
38 #define XDIM    0
39 #define YDIM    1
40 #define ZDIM    2
41
42 #define MAX_MODIFIED_VERTICES   32
43 int             Modified_vertices[MAX_MODIFIED_VERTICES];
44 int             Modified_vertex_index = 0;
45
46 // ------------------------------------------------------------------------------------------
47 void validate_modified_segments(void)
48 {
49         int     v,w,v0,seg;
50         char    modified_segments[MAX_SEGMENTS];
51
52         for (v=0; v<=Highest_segment_index; v++)
53                 modified_segments[v] = 0;
54
55         for (v=0; v<Modified_vertex_index; v++) {
56                 v0 = Modified_vertices[v];
57
58                 for (seg = 0; seg <= Highest_segment_index; seg++) {
59                         short *vp = Segments[seg].verts;
60                         if (Segments[seg].segnum != -1)
61                                 for (w=0; w<MAX_VERTICES_PER_SEGMENT; w++)
62                                         if (*vp++ == v0)
63                                                 modified_segments[seg] = 1;
64                 }
65         }
66
67         for (v=0; v<=Highest_segment_index; v++)
68                 if (modified_segments[v]) {
69                         int     s;
70
71                         // mprintf(0, "Validating segment #%04i\n", v);
72                         validate_segment(&Segments[v]);
73                         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++) {
74                                 Num_tilings = 1;
75                                 assign_default_uvs_to_side(&Segments[v], s);
76                         }
77                 }
78 }
79
80 // ------------------------------------------------------------------------------------------
81 //      Scale vertex *vertp by vector *vp, scaled by scale factor scale_factor
82 void scale_vert_aux(int vertex_ind, vms_vector *vp, fix scale_factor)
83 {
84         vms_vector      *vertp = &Vertices[vertex_ind];
85
86         vertp->x += fixmul(vp->x,scale_factor)/2;
87         vertp->y += fixmul(vp->y,scale_factor)/2;
88         vertp->z += fixmul(vp->z,scale_factor)/2;
89
90         Assert(Modified_vertex_index < MAX_MODIFIED_VERTICES);
91         Modified_vertices[Modified_vertex_index++] = vertex_ind;
92 }
93
94 // ------------------------------------------------------------------------------------------
95 void scale_vert(segment *sp, int vertex_ind, vms_vector *vp, fix scale_factor)
96 {
97         switch (SegSizeMode) {
98                 case SEGSIZEMODE_FREE:
99                         if (is_free_vertex(vertex_ind))
100                                 scale_vert_aux(vertex_ind, vp, scale_factor);
101                         break;
102                 case SEGSIZEMODE_ALL:
103                         scale_vert_aux(vertex_ind, vp, scale_factor);
104                         break;
105                 case SEGSIZEMODE_CURSIDE: {
106                         int     v;
107                         for (v=0; v<4; v++)
108                                 if (sp->verts[Side_to_verts[Curside][v]] == vertex_ind)
109                                         scale_vert_aux(vertex_ind, vp, scale_factor);
110                         break;
111                 }
112                 case SEGSIZEMODE_EDGE: {
113                         int     v;
114
115                         for (v=0; v<2; v++)
116                                 if (sp->verts[Side_to_verts[Curside][(Curedge+v)%4]] == vertex_ind)
117                                         scale_vert_aux(vertex_ind, vp, scale_factor);
118                         break;
119                 }
120                 case SEGSIZEMODE_VERTEX:
121                         if (sp->verts[Side_to_verts[Curside][Curvert]] == vertex_ind)
122                                 scale_vert_aux(vertex_ind, vp, scale_factor);
123                         break;
124                 default:
125                         Error("Unsupported SegSizeMode in ksegsize.c/scale_vert = %i\n", SegSizeMode);
126         }
127
128 }
129
130 // ------------------------------------------------------------------------------------------
131 void scale_free_verts(segment *sp, vms_vector *vp, int side, fix scale_factor)
132 {
133         int             v;
134         sbyte           *verts;
135         int             vertex_ind;
136
137         verts = Side_to_verts[side];
138
139         for (v=0; v<4; v++) {
140                 vertex_ind = sp->verts[(int) verts[v]];
141                 if (SegSizeMode || is_free_vertex(vertex_ind))
142                         scale_vert(sp, vertex_ind, vp, scale_factor);
143         }
144
145 }
146
147
148 // -----------------------------------------------------------------------------
149 //      Make segment *sp bigger in dimension dimension by amount amount.
150 void med_scale_segment_new(segment *sp, int dimension, fix amount)
151 {
152         vms_matrix      mat;
153
154         Modified_vertex_index = 0;
155
156         med_extract_matrix_from_segment(sp, &mat);
157
158         switch (dimension) {
159                 case XDIM:
160                         scale_free_verts(sp, &mat.rvec, WLEFT,   -amount);
161                         scale_free_verts(sp, &mat.rvec, WRIGHT,  +amount);
162                         break;
163                 case YDIM:
164                         scale_free_verts(sp, &mat.uvec, WBOTTOM, -amount);
165                         scale_free_verts(sp, &mat.uvec, WTOP,    +amount);
166                         break;
167                 case ZDIM:
168                         scale_free_verts(sp, &mat.fvec, WFRONT,  -amount);
169                         scale_free_verts(sp, &mat.fvec, WBACK,   +amount);
170                         break;
171         }
172
173         validate_modified_segments();
174 }
175
176 // ------------------------------------------------------------------------------------------
177 //      Extract a vector from a segment.  The vector goes from the start face to the end face.
178 //      The point on each face is the average of the four points forming the face.
179 void extract_vector_from_segment_side(segment *sp, int side, vms_vector *vp, int vla, int vlb, int vra, int vrb)
180 {
181         vms_vector      v1, v2;
182
183         vm_vec_sub(&v1,&Vertices[sp->verts[Side_to_verts[side][vra]]],&Vertices[sp->verts[Side_to_verts[side][vla]]]);
184         vm_vec_sub(&v2,&Vertices[sp->verts[Side_to_verts[side][vrb]]],&Vertices[sp->verts[Side_to_verts[side][vlb]]]);
185         vm_vec_add(vp, &v1, &v2);
186
187         vm_vec_scale(vp, F1_0/2);
188 }
189
190 // ------------------------------------------------------------------------------------------
191 //      Extract the right vector from segment *sp, return in *vp.
192 //      The forward vector is defined to be the vector from the the center of the left face of the segment
193 // to the center of the right face of the segment.
194 void med_extract_right_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp)
195 {
196         extract_vector_from_segment_side(sp, sidenum, vp, 3, 2, 0, 1);
197 }
198
199 // ------------------------------------------------------------------------------------------
200 //      Extract the up vector from segment *sp, return in *vp.
201 //      The forward vector is defined to be the vector from the the center of the bottom face of the segment
202 // to the center of the top face of the segment.
203 void med_extract_up_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp)
204 {
205         extract_vector_from_segment_side(sp, sidenum, vp, 1, 2, 0, 3);
206 }
207
208
209 // -----------------------------------------------------------------------------
210 //      Increase the size of Cursegp in dimension dimension by amount
211 int segsize_common(int dimension, fix amount)
212 {
213         int     i;
214         int     propagated[MAX_SIDES_PER_SEGMENT];
215         vms_vector      uvec, rvec, fvec, scalevec;
216
217         Degenerate_segment_found = 0;
218
219         med_scale_segment_new(Cursegp, dimension, amount);
220
221         med_extract_up_vector_from_segment_side(Cursegp, Curside, &uvec);
222         med_extract_right_vector_from_segment_side(Cursegp, Curside, &rvec);
223         extract_forward_vector_from_segment(Cursegp, &fvec);
224
225         scalevec.x = vm_vec_mag(&rvec);
226         scalevec.y = vm_vec_mag(&uvec);
227         scalevec.z = vm_vec_mag(&fvec);
228
229         if (Degenerate_segment_found) {
230                 Degenerate_segment_found = 0;
231                 // mprintf(0, "Applying scale would create degenerate segments.  Aborting scale.\n");
232                 editor_status("Applying scale would create degenerate segments.  Aborting scale.");
233                 med_scale_segment_new(Cursegp, dimension, -amount);
234                 return 1;
235         }
236
237         med_create_new_segment(&scalevec);
238
239         //      For all segments to which Cursegp is connected, propagate tmap (uv coordinates) from the connected
240         //      segment back to Cursegp.  This will meaningfully propagate uv coordinates to all sides which havve
241         //      an incident edge.  It will also do some sides more than once.  And it is probably just not what you want.
242         for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
243                 propagated[i] = 0;
244
245         for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
246                 if (IS_CHILD(Cursegp->children[i])) {
247                         int     s;
248                         for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
249                                 propagated[s]++;
250                         propagated[(int) Side_opposite[i]]--;
251                         med_propagate_tmaps_to_segments(&Segments[Cursegp->children[i]],Cursegp,1);
252                 }
253
254         //      Now, for all sides that were not adjacent to another side, and therefore did not get tmaps
255         //      propagated to them, treat as a back side.
256         for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
257                 if (!propagated[i]) {
258                         med_propagate_tmaps_to_back_side(Cursegp, i, 1);
259                 }
260
261         //      New stuff, assign default texture to all affected sides.
262
263         Update_flags |= UF_WORLD_CHANGED;
264         mine_changed = 1;
265         return 1;
266 }
267
268 // -----------------------------------------------------------------------------
269 // ---------- segment size control ----------
270
271 int IncreaseSegLength()
272 {
273         return segsize_common(ZDIM,+F1_0);
274 }
275
276 int DecreaseSegLength()
277 {
278         return segsize_common(ZDIM,-F1_0);
279 }
280
281 int DecreaseSegWidth()
282 {
283         return segsize_common(XDIM,-F1_0);
284 }
285
286 int IncreaseSegWidth()
287 {
288         return segsize_common(XDIM,+F1_0);
289 }
290
291 int IncreaseSegHeight()
292 {
293         return segsize_common(YDIM,+F1_0);
294 }
295
296 int DecreaseSegHeight()
297 {
298         return segsize_common(YDIM,-F1_0);
299 }
300
301
302 int IncreaseSegLengthBig()
303 {
304         return segsize_common(ZDIM,+5 * F1_0);
305 }
306
307 int DecreaseSegLengthBig()
308 {
309         return segsize_common(ZDIM,-5 * F1_0);
310 }
311
312 int DecreaseSegWidthBig()
313 {
314         return segsize_common(XDIM,-5 * F1_0);
315 }
316
317 int IncreaseSegWidthBig()
318 {
319         return segsize_common(XDIM,+5 * F1_0);
320 }
321
322 int IncreaseSegHeightBig()
323 {
324         return segsize_common(YDIM,+5 * F1_0);
325 }
326
327 int DecreaseSegHeightBig()
328 {
329         return segsize_common(YDIM,-5 * F1_0);
330 }
331
332
333 int IncreaseSegLengthDefault()
334 {
335         return segsize_common(ZDIM,+40 *F1_0);
336 }
337
338 int DecreaseSegLengthDefault()
339 {
340         return segsize_common(ZDIM,-40*F1_0);
341 }
342
343 int IncreaseSegWidthDefault()
344 {
345         return segsize_common(XDIM,+40*F1_0);
346 }
347
348 int DecreaseSegWidthDefault()
349 {
350         return segsize_common(XDIM,-40*F1_0);
351 }
352
353 int IncreaseSegHeightDefault()
354 {
355         return segsize_common(YDIM,+40 * F1_0);
356 }
357
358 int DecreaseSegHeightDefault()
359 {
360         return segsize_common(YDIM,-40 * F1_0);
361 }
362
363
364
365 //      ---------------------------------------------------------------------------
366 int ToggleSegSizeMode(void)
367 {
368         SegSizeMode++;
369         if (SegSizeMode > SEGSIZEMODE_MAX)
370                 SegSizeMode = SEGSIZEMODE_MIN;
371
372         return 1;
373 }
374
375 //      ---------------------------------------------------------------------------
376 int     PerturbCursideCommon(fix amount)
377 {
378         int                     saveSegSizeMode = SegSizeMode;
379         vms_vector      fvec, rvec, uvec;
380         fix                     fmag, rmag, umag;
381         int                     v;
382
383         SegSizeMode = SEGSIZEMODE_CURSIDE;
384
385         Modified_vertex_index = 0;
386
387         extract_forward_vector_from_segment(Cursegp, &fvec);
388         extract_right_vector_from_segment(Cursegp, &rvec);
389         extract_up_vector_from_segment(Cursegp, &uvec);
390
391         fmag = vm_vec_mag(&fvec);
392         rmag = vm_vec_mag(&rvec);
393         umag = vm_vec_mag(&uvec);
394
395         for (v=0; v<4; v++) {
396                 vms_vector perturb_vec;
397
398                 perturb_vec.x = fixmul(rmag, d_rand()*2 - 32767);
399                 perturb_vec.y = fixmul(umag, d_rand()*2 - 32767);
400                 perturb_vec.z = fixmul(fmag, d_rand()*2 - 32767);
401
402                 scale_vert(Cursegp, Cursegp->verts[Side_to_verts[Curside][v]], &perturb_vec, amount);
403         }
404
405 //      validate_segment(Cursegp);
406 //      if (SegSizeMode) {
407 //              for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
408 //                      if (Cursegp->children[i] != -1)
409 //                              validate_segment(&Segments[Cursegp->children[i]]);
410 //      }
411
412         validate_modified_segments();
413         SegSizeMode = saveSegSizeMode;
414
415         Update_flags |= UF_WORLD_CHANGED;
416         mine_changed = 1;
417
418         return 1;
419 }
420
421 //      ---------------------------------------------------------------------------
422 int     PerturbCurside(void)
423 {
424         PerturbCursideCommon(F1_0/10);
425
426         return 1;
427 }
428
429 //      ---------------------------------------------------------------------------
430 int     PerturbCursideBig(void)
431 {
432         PerturbCursideCommon(F1_0/2);
433
434         return 1;
435 }