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