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