1 /* $Id: ksegsize.c,v 1.3 2004-12-19 15:21:11 btb Exp $ */
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.
17 * Functions for sizing segments
22 static char rcsid[] = "$Id: ksegsize.c,v 1.3 2004-12-19 15:21:11 btb Exp $";
42 #define MAX_MODIFIED_VERTICES 32
43 int Modified_vertices[MAX_MODIFIED_VERTICES];
44 int Modified_vertex_index = 0;
46 // ------------------------------------------------------------------------------------------
47 void validate_modified_segments(void)
50 char modified_segments[MAX_SEGMENTS];
52 for (v=0; v<=Highest_segment_index; v++)
53 modified_segments[v] = 0;
55 for (v=0; v<Modified_vertex_index; v++) {
56 v0 = Modified_vertices[v];
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++)
63 modified_segments[seg] = 1;
67 for (v=0; v<=Highest_segment_index; v++)
68 if (modified_segments[v]) {
71 // mprintf(0, "Validating segment #%04i\n", v);
72 validate_segment(&Segments[v]);
73 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++) {
75 assign_default_uvs_to_side(&Segments[v], s);
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)
84 vms_vector *vertp = &Vertices[vertex_ind];
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;
90 Assert(Modified_vertex_index < MAX_MODIFIED_VERTICES);
91 Modified_vertices[Modified_vertex_index++] = vertex_ind;
94 // ------------------------------------------------------------------------------------------
95 void scale_vert(segment *sp, int vertex_ind, vms_vector *vp, fix scale_factor)
97 switch (SegSizeMode) {
98 case SEGSIZEMODE_FREE:
99 if (is_free_vertex(vertex_ind))
100 scale_vert_aux(vertex_ind, vp, scale_factor);
102 case SEGSIZEMODE_ALL:
103 scale_vert_aux(vertex_ind, vp, scale_factor);
105 case SEGSIZEMODE_CURSIDE: {
108 if (sp->verts[Side_to_verts[Curside][v]] == vertex_ind)
109 scale_vert_aux(vertex_ind, vp, scale_factor);
112 case SEGSIZEMODE_EDGE: {
116 if (sp->verts[Side_to_verts[Curside][(Curedge+v)%4]] == vertex_ind)
117 scale_vert_aux(vertex_ind, vp, scale_factor);
120 case SEGSIZEMODE_VERTEX:
121 if (sp->verts[Side_to_verts[Curside][Curvert]] == vertex_ind)
122 scale_vert_aux(vertex_ind, vp, scale_factor);
125 Error("Unsupported SegSizeMode in ksegsize.c/scale_vert = %i\n", SegSizeMode);
130 // ------------------------------------------------------------------------------------------
131 void scale_free_verts(segment *sp, vms_vector *vp, int side, fix scale_factor)
137 verts = Side_to_verts[side];
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);
148 // -----------------------------------------------------------------------------
149 // Make segment *sp bigger in dimension dimension by amount amount.
150 void med_scale_segment_new(segment *sp, int dimension, fix amount)
154 Modified_vertex_index = 0;
156 med_extract_matrix_from_segment(sp, &mat);
160 scale_free_verts(sp, &mat.rvec, WLEFT, -amount);
161 scale_free_verts(sp, &mat.rvec, WRIGHT, +amount);
164 scale_free_verts(sp, &mat.uvec, WBOTTOM, -amount);
165 scale_free_verts(sp, &mat.uvec, WTOP, +amount);
168 scale_free_verts(sp, &mat.fvec, WFRONT, -amount);
169 scale_free_verts(sp, &mat.fvec, WBACK, +amount);
173 validate_modified_segments();
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)
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);
187 vm_vec_scale(vp, F1_0/2);
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)
196 extract_vector_from_segment_side(sp, sidenum, vp, 3, 2, 0, 1);
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)
205 extract_vector_from_segment_side(sp, sidenum, vp, 1, 2, 0, 3);
209 // -----------------------------------------------------------------------------
210 // Increase the size of Cursegp in dimension dimension by amount
211 int segsize_common(int dimension, fix amount)
214 int propagated[MAX_SIDES_PER_SEGMENT];
215 vms_vector uvec, rvec, fvec, scalevec;
217 Degenerate_segment_found = 0;
219 med_scale_segment_new(Cursegp, dimension, amount);
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);
225 scalevec.x = vm_vec_mag(&rvec);
226 scalevec.y = vm_vec_mag(&uvec);
227 scalevec.z = vm_vec_mag(&fvec);
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);
237 med_create_new_segment(&scalevec);
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++)
245 for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
246 if (IS_CHILD(Cursegp->children[i])) {
248 for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
250 propagated[(int) Side_opposite[i]]--;
251 med_propagate_tmaps_to_segments(&Segments[Cursegp->children[i]],Cursegp,1);
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);
261 // New stuff, assign default texture to all affected sides.
263 Update_flags |= UF_WORLD_CHANGED;
268 // -----------------------------------------------------------------------------
269 // ---------- segment size control ----------
271 int IncreaseSegLength()
273 return segsize_common(ZDIM,+F1_0);
276 int DecreaseSegLength()
278 return segsize_common(ZDIM,-F1_0);
281 int DecreaseSegWidth()
283 return segsize_common(XDIM,-F1_0);
286 int IncreaseSegWidth()
288 return segsize_common(XDIM,+F1_0);
291 int IncreaseSegHeight()
293 return segsize_common(YDIM,+F1_0);
296 int DecreaseSegHeight()
298 return segsize_common(YDIM,-F1_0);
302 int IncreaseSegLengthBig()
304 return segsize_common(ZDIM,+5 * F1_0);
307 int DecreaseSegLengthBig()
309 return segsize_common(ZDIM,-5 * F1_0);
312 int DecreaseSegWidthBig()
314 return segsize_common(XDIM,-5 * F1_0);
317 int IncreaseSegWidthBig()
319 return segsize_common(XDIM,+5 * F1_0);
322 int IncreaseSegHeightBig()
324 return segsize_common(YDIM,+5 * F1_0);
327 int DecreaseSegHeightBig()
329 return segsize_common(YDIM,-5 * F1_0);
333 int IncreaseSegLengthDefault()
335 return segsize_common(ZDIM,+40 *F1_0);
338 int DecreaseSegLengthDefault()
340 return segsize_common(ZDIM,-40*F1_0);
343 int IncreaseSegWidthDefault()
345 return segsize_common(XDIM,+40*F1_0);
348 int DecreaseSegWidthDefault()
350 return segsize_common(XDIM,-40*F1_0);
353 int IncreaseSegHeightDefault()
355 return segsize_common(YDIM,+40 * F1_0);
358 int DecreaseSegHeightDefault()
360 return segsize_common(YDIM,-40 * F1_0);
365 // ---------------------------------------------------------------------------
366 int ToggleSegSizeMode(void)
369 if (SegSizeMode > SEGSIZEMODE_MAX)
370 SegSizeMode = SEGSIZEMODE_MIN;
375 // ---------------------------------------------------------------------------
376 int PerturbCursideCommon(fix amount)
378 int saveSegSizeMode = SegSizeMode;
379 vms_vector fvec, rvec, uvec;
380 fix fmag, rmag, umag;
383 SegSizeMode = SEGSIZEMODE_CURSIDE;
385 Modified_vertex_index = 0;
387 extract_forward_vector_from_segment(Cursegp, &fvec);
388 extract_right_vector_from_segment(Cursegp, &rvec);
389 extract_up_vector_from_segment(Cursegp, &uvec);
391 fmag = vm_vec_mag(&fvec);
392 rmag = vm_vec_mag(&rvec);
393 umag = vm_vec_mag(&uvec);
395 for (v=0; v<4; v++) {
396 vms_vector perturb_vec;
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);
402 scale_vert(Cursegp, Cursegp->verts[Side_to_verts[Curside][v]], &perturb_vec, amount);
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]]);
412 validate_modified_segments();
413 SegSizeMode = saveSegSizeMode;
415 Update_flags |= UF_WORLD_CHANGED;
421 // ---------------------------------------------------------------------------
422 int PerturbCurside(void)
424 PerturbCursideCommon(F1_0/10);
429 // ---------------------------------------------------------------------------
430 int PerturbCursideBig(void)
432 PerturbCursideCommon(F1_0/2);