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