]> icculus.org git repositories - btb/d2x.git/blob - main/editor/texture.c
remove rcs tags
[btb/d2x.git] / main / editor / texture.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  * Texture map assignment.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "conf.h"
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <math.h>
28 #include <string.h>
29
30 #include "inferno.h"
31 #include "segment.h"
32 #include "seguvs.h"
33 #include "editor.h"
34
35 #include "fix.h"
36 #include "mono.h"
37 #include "error.h"
38 #include "kdefs.h"
39
40 void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum);
41 void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter);
42
43 //      -----------------------------------------------------------
44 int     TexFlipX()
45 {
46         uvl     uvcenter;
47         fix     rotmat[4];
48
49         compute_uv_side_center(&uvcenter, Cursegp, Curside);
50
51         //      Create a rotation matrix
52         rotmat[0] = -0xffff;
53         rotmat[1] = 0;
54         rotmat[2] = 0;
55         rotmat[3] = 0xffff;
56
57         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
58
59         Update_flags |= UF_WORLD_CHANGED;
60
61         return  1;
62 }
63
64 //      -----------------------------------------------------------
65 int     TexFlipY()
66 {
67         uvl     uvcenter;
68         fix     rotmat[4];
69
70         compute_uv_side_center(&uvcenter, Cursegp, Curside);
71
72         //      Create a rotation matrix
73         rotmat[0] = 0xffff;
74         rotmat[1] = 0;
75         rotmat[2] = 0;
76         rotmat[3] = -0xffff;
77
78         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
79
80         Update_flags |= UF_WORLD_CHANGED;
81
82         return  1;
83 }
84
85 //      -----------------------------------------------------------
86 int DoTexSlideLeft(int value)
87 {
88         side    *sidep;
89         uvl     duvl03;
90         fix     dist;
91         sbyte   *vp;
92         int     v;
93
94         vp = Side_to_verts[Curside];
95         sidep = &Cursegp->sides[Curside];
96
97         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]);
98         dist *= value;
99         if (dist < F1_0/(64*value))
100                 dist = F1_0/(64*value);
101
102         duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist);
103         duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist);
104
105         for (v=0; v<4; v++) {
106                 sidep->uvls[v].u -= duvl03.u;
107                 sidep->uvls[v].v -= duvl03.v;
108         }
109
110         Update_flags |= UF_WORLD_CHANGED;
111
112         return  1;
113 }
114
115 int TexSlideLeft()
116 {
117         return DoTexSlideLeft(3);
118 }
119
120 int TexSlideLeftBig()
121 {
122         return DoTexSlideLeft(1);
123 }
124
125 //      -----------------------------------------------------------
126 int DoTexSlideUp(int value)
127 {
128         side    *sidep;
129         uvl     duvl03;
130         fix     dist;
131         sbyte   *vp;
132         int     v;
133
134         vp = Side_to_verts[Curside];
135         sidep = &Cursegp->sides[Curside];
136
137         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]);
138         dist *= value;
139
140         if (dist < F1_0/(64*value))
141                 dist = F1_0/(64*value);
142
143         duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist);
144         duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist);
145
146         for (v=0; v<4; v++) {
147                 sidep->uvls[v].u -= duvl03.u;
148                 sidep->uvls[v].v -= duvl03.v;
149         }
150
151         Update_flags |= UF_WORLD_CHANGED;
152
153         return  1;
154 }
155
156 int TexSlideUp()
157 {
158         return DoTexSlideUp(3);
159 }
160
161 int TexSlideUpBig()
162 {
163         return DoTexSlideUp(1);
164 }
165
166
167 //      -----------------------------------------------------------
168 int DoTexSlideDown(int value)
169 {
170         side    *sidep;
171         uvl     duvl03;
172         fix     dist;
173         sbyte   *vp;
174         int     v;
175
176         vp = Side_to_verts[Curside];
177         sidep = &Cursegp->sides[Curside];
178
179         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]);
180         dist *= value;
181         if (dist < F1_0/(64*value))
182                 dist = F1_0/(64*value);
183
184         duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist);
185         duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist);
186
187         for (v=0; v<4; v++) {
188                 sidep->uvls[v].u += duvl03.u;
189                 sidep->uvls[v].v += duvl03.v;
190         }
191
192         Update_flags |= UF_WORLD_CHANGED;
193
194         return  1;
195 }
196
197 int TexSlideDown()
198 {
199         return DoTexSlideDown(3);
200 }
201
202 int TexSlideDownBig()
203 {
204         return DoTexSlideDown(1);
205 }
206
207 //      -----------------------------------------------------------
208 //      Compute the center of the side in u,v coordinates.
209 void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum)
210 {
211         int     v;
212         side    *sidep = &segp->sides[sidenum];
213
214         uvcenter->u = 0;
215         uvcenter->v = 0;
216
217         for (v=0; v<4; v++) {
218                 uvcenter->u += sidep->uvls[v].u;
219                 uvcenter->v += sidep->uvls[v].v;
220         }
221
222         uvcenter->u /= 4;
223         uvcenter->v /= 4;
224 }
225
226
227 //      -----------------------------------------------------------
228 //      rotate point *uv by matrix rotmat, return *uvrot
229 void rotate_uv_point(uvl *uvrot, fix *rotmat, uvl *uv, uvl *uvcenter)
230 {
231         uvrot->u = fixmul(uv->u - uvcenter->u,rotmat[0]) + fixmul(uv->v - uvcenter->v,rotmat[1]) + uvcenter->u;
232         uvrot->v = fixmul(uv->u - uvcenter->u,rotmat[2]) + fixmul(uv->v - uvcenter->v,rotmat[3]) + uvcenter->v;
233 }
234
235 //      -----------------------------------------------------------
236 //      Compute the center of the side in u,v coordinates.
237 void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter)
238 {
239         int     v;
240         side    *sidep = &segp->sides[sidenum];
241         uvl     tuv;
242
243         for (v=0; v<4; v++) {
244                 rotate_uv_point(&tuv, rotmat, &sidep->uvls[v], uvcenter);
245                 sidep->uvls[v] = tuv;
246         }
247 }
248
249 //      -----------------------------------------------------------
250 //      ang is in 0..ffff = 0..359.999 degrees
251 //      rotmat is filled in with 4 fixes
252 void create_2d_rotation_matrix(fix *rotmat, fix ang)
253 {
254         fix     sinang, cosang;
255
256         fix_sincos(ang, &sinang, &cosang);
257
258         rotmat[0] = cosang;
259         rotmat[1] = sinang;
260         rotmat[2] = -sinang;
261         rotmat[3] = cosang;
262         
263 }
264
265
266 //      -----------------------------------------------------------
267 int DoTexRotateLeft(int value)
268 {
269         uvl     uvcenter;
270         fix     rotmat[4];
271
272         compute_uv_side_center(&uvcenter, Cursegp, Curside);
273
274         //      Create a rotation matrix
275         create_2d_rotation_matrix(rotmat, -F1_0/value);
276
277         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
278
279         Update_flags |= UF_WORLD_CHANGED;
280
281         return  1;
282 }
283
284 int TexRotateLeft()
285 {
286         return DoTexRotateLeft(192);
287 }
288
289 int TexRotateLeftBig()
290 {
291         return DoTexRotateLeft(64);
292 }
293
294
295 //      -----------------------------------------------------------
296 int DoTexSlideRight(int value)
297 {
298         side    *sidep;
299         uvl     duvl03;
300         fix     dist;
301         sbyte   *vp;
302         int     v;
303
304         vp = Side_to_verts[Curside];
305         sidep = &Cursegp->sides[Curside];
306
307         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]);
308         dist *= value;
309         if (dist < F1_0/(64*value))
310                 dist = F1_0/(64*value);
311
312         duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist);
313         duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist);
314
315         for (v=0; v<4; v++) {
316                 sidep->uvls[v].u += duvl03.u;
317                 sidep->uvls[v].v += duvl03.v;
318         }
319
320         Update_flags |= UF_WORLD_CHANGED;
321
322         return  1;
323 }
324
325 int TexSlideRight()
326 {
327         return DoTexSlideRight(3);
328 }
329
330 int TexSlideRightBig()
331 {
332         return DoTexSlideRight(1);
333 }
334
335 //      -----------------------------------------------------------
336 int DoTexRotateRight(int value)
337 {
338         uvl     uvcenter;
339         fix     rotmat[4];
340
341         compute_uv_side_center(&uvcenter, Cursegp, Curside);
342
343         //      Create a rotation matrix
344         create_2d_rotation_matrix(rotmat, F1_0/value);
345
346         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
347
348         Update_flags |= UF_WORLD_CHANGED;
349
350         return  1;
351 }
352
353 int TexRotateRight()
354 {
355         return DoTexRotateRight(192);
356 }
357
358 int TexRotateRightBig()
359 {
360         return DoTexRotateRight(64);
361 }
362
363 //      -----------------------------------------------------------
364 int     TexSelectActiveEdge()
365 {
366         return  1;
367 }
368
369 //      -----------------------------------------------------------
370 int     TexRotate90Degrees()
371 {
372         uvl     uvcenter;
373         fix     rotmat[4];
374
375         compute_uv_side_center(&uvcenter, Cursegp, Curside);
376
377         //      Create a rotation matrix
378         create_2d_rotation_matrix(rotmat, F1_0/4);
379
380         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
381
382         Update_flags |= UF_WORLD_CHANGED;
383
384         return  1;
385 }
386
387 //      -----------------------------------------------------------
388 int     TexSetDefault()
389 {
390         Num_tilings = 1;
391
392         Stretch_scale_x = F1_0;
393         Stretch_scale_y = F1_0;
394
395         assign_default_uvs_to_side(Cursegp,Curside);
396
397         Update_flags |= UF_GAME_VIEW_CHANGED;
398         return  1;
399 }
400
401 //      -----------------------------------------------------------
402 int     TexIncreaseTiling()
403 {
404
405         Num_tilings++;
406         assign_default_uvs_to_side(Cursegp, Curside);
407         Update_flags |= UF_GAME_VIEW_CHANGED;
408
409         return  1;
410 }
411
412 //      -----------------------------------------------------------
413 int     TexDecreaseTiling()
414 {
415
416         if (--Num_tilings < 1)
417                 Num_tilings = 1;
418
419         assign_default_uvs_to_side(Cursegp, Curside);
420         Update_flags |= UF_GAME_VIEW_CHANGED;
421
422         return  1;
423 }
424
425
426 //      direction = -1 or 1 depending on direction
427 int     TexStretchCommon(int direction)
428 {
429         fix     *sptr;
430
431         if ((Curedge == 0) || (Curedge == 2))
432                 sptr = &Stretch_scale_x;
433         else
434                 sptr = &Stretch_scale_y;
435
436         *sptr += direction*F1_0/64;
437
438         if (*sptr < F1_0/16)
439                 *sptr = F1_0/16;
440
441         if (*sptr > 2*F1_0)
442                 *sptr = 2*F1_0;
443
444         stretch_uvs_from_curedge(Cursegp, Curside);
445
446         editor_status("Stretch scale = %7.4f, use Set Default to return to 1.0", f2fl(*sptr));
447
448         Update_flags |= UF_GAME_VIEW_CHANGED;
449         return  1;
450
451 }
452
453 int     TexStretchDown(void)
454 {
455         return TexStretchCommon(-1);
456
457 }
458
459 int     TexStretchUp(void)
460 {
461         return TexStretchCommon(1);
462
463 }
464