]> icculus.org git repositories - btb/d2x.git/blob - main/editor/texture.c
imported missing editor files from d1x
[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  * $Source: /cvs/cvsroot/d2x/main/editor/texture.c,v $
15  * $Revision: 1.1 $
16  * $Author: btb $
17  * $Date: 2004-12-19 13:54:27 $
18  * 
19  * Texture map assignment.
20  * 
21  * $Log: not supported by cvs2svn $
22  * Revision 1.2  2003/03/09 06:34:09  donut
23  * change byte typedef to sbyte to avoid conflict with win32 byte which is unsigned
24  *
25  * Revision 1.1.1.1  1999/06/14 22:04:34  donut
26  * Import of d1x 1.37 source.
27  *
28  * Revision 2.0  1995/02/27  11:34:50  john
29  * Version 2.0! No anonymous unions, Watcom 10.0, with no need
30  * for bitmaps.tbl.
31  * 
32  * Revision 1.13  1994/08/04  19:13:15  matt
33  * Changed a bunch of vecmat calls to use multiple-function routines, and to
34  * allow the use of C macros for some functions
35  * 
36  * Revision 1.12  1994/08/03  10:31:56  mike
37  * Texture map propagation without uv assignment.
38  * 
39  * Revision 1.11  1994/07/14  19:36:34  yuan
40  * Tuning texture slides.
41  * 
42  * Revision 1.10  1994/07/14  19:29:08  yuan
43  * Fixed sliding.
44  * 
45  * Revision 1.9  1994/07/14  14:43:06  yuan
46  * Added 3x rotation.
47  * 
48  * Revision 1.8  1994/07/14  11:12:42  yuan
49  * Made sliding 3x more sensitive
50  * 
51  * Revision 1.7  1994/07/14  10:49:56  yuan
52  * Made texture rotation 3x finer
53  * 
54  * Revision 1.6  1994/02/14  12:06:00  mike
55  * change segment data structure.
56  * 
57  * Revision 1.5  1993/12/06  13:26:52  mike
58  * Make rotation and sliding work for triangulated sides.
59  * 
60  * Revision 1.4  1993/12/04  17:18:46  mike
61  * Add tiling functions, set_default.
62  * 
63  * Revision 1.3  1993/12/03  18:39:12  unknown
64  * Add texture map sliding, allow to work on triangulated sides.
65  * 
66  * Revision 1.2  1993/11/30  17:06:09  mike
67  * Texture map functions.
68  * 
69  * Revision 1.1  1993/11/29  16:00:57  mike
70  * Initial revision
71  * 
72  * 
73  */
74
75
76 #ifdef RCS
77 static char rcsid[] = "$Id: texture.c,v 1.1 2004-12-19 13:54:27 btb Exp $";
78 #endif
79
80 #include <stdio.h>
81 #include <stdlib.h>
82 #include <stdarg.h>
83 #include <math.h>
84 #include <string.h>
85
86 #include "inferno.h"
87 #include "segment.h"
88 #include "seguvs.h"
89 #include "editor.h"
90
91 #include "fix.h"
92 #include "mono.h"
93 #include "error.h"
94 #include "kdefs.h"
95
96 void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum);
97 void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter);
98
99 //      -----------------------------------------------------------
100 int     TexFlipX()
101 {
102         uvl     uvcenter;
103         fix     rotmat[4];
104
105         compute_uv_side_center(&uvcenter, Cursegp, Curside);
106
107         //      Create a rotation matrix
108         rotmat[0] = -0xffff;
109         rotmat[1] = 0;
110         rotmat[2] = 0;
111         rotmat[3] = 0xffff;
112
113         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
114
115         Update_flags |= UF_WORLD_CHANGED;
116
117         return  1;
118 }
119
120 //      -----------------------------------------------------------
121 int     TexFlipY()
122 {
123         uvl     uvcenter;
124         fix     rotmat[4];
125
126         compute_uv_side_center(&uvcenter, Cursegp, Curside);
127
128         //      Create a rotation matrix
129         rotmat[0] = 0xffff;
130         rotmat[1] = 0;
131         rotmat[2] = 0;
132         rotmat[3] = -0xffff;
133
134         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
135
136         Update_flags |= UF_WORLD_CHANGED;
137
138         return  1;
139 }
140
141 //      -----------------------------------------------------------
142 int DoTexSlideLeft(int value)
143 {
144         side    *sidep;
145         uvl     duvl03;
146         fix     dist;
147         sbyte   *vp;
148         int     v;
149
150         vp = Side_to_verts[Curside];
151         sidep = &Cursegp->sides[Curside];
152
153         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]);
154         dist *= value;
155         if (dist < F1_0/(64*value))
156                 dist = F1_0/(64*value);
157
158         duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist);
159         duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist);
160
161         for (v=0; v<4; v++) {
162                 sidep->uvls[v].u -= duvl03.u;
163                 sidep->uvls[v].v -= duvl03.v;
164         }
165
166         Update_flags |= UF_WORLD_CHANGED;
167
168         return  1;
169 }
170
171 int TexSlideLeft()
172 {
173         return DoTexSlideLeft(3);
174 }
175
176 int TexSlideLeftBig()
177 {
178         return DoTexSlideLeft(1);
179 }
180
181 //      -----------------------------------------------------------
182 int DoTexSlideUp(int value)
183 {
184         side    *sidep;
185         uvl     duvl03;
186         fix     dist;
187         sbyte   *vp;
188         int     v;
189
190         vp = Side_to_verts[Curside];
191         sidep = &Cursegp->sides[Curside];
192
193         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]);
194         dist *= value;
195
196         if (dist < F1_0/(64*value))
197                 dist = F1_0/(64*value);
198
199         duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist);
200         duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist);
201
202         for (v=0; v<4; v++) {
203                 sidep->uvls[v].u -= duvl03.u;
204                 sidep->uvls[v].v -= duvl03.v;
205         }
206
207         Update_flags |= UF_WORLD_CHANGED;
208
209         return  1;
210 }
211
212 int TexSlideUp()
213 {
214         return DoTexSlideUp(3);
215 }
216
217 int TexSlideUpBig()
218 {
219         return DoTexSlideUp(1);
220 }
221
222
223 //      -----------------------------------------------------------
224 int DoTexSlideDown(int value)
225 {
226         side    *sidep;
227         uvl     duvl03;
228         fix     dist;
229         sbyte   *vp;
230         int     v;
231
232         vp = Side_to_verts[Curside];
233         sidep = &Cursegp->sides[Curside];
234
235         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]);
236         dist *= value;
237         if (dist < F1_0/(64*value))
238                 dist = F1_0/(64*value);
239
240         duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist);
241         duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist);
242
243         for (v=0; v<4; v++) {
244                 sidep->uvls[v].u += duvl03.u;
245                 sidep->uvls[v].v += duvl03.v;
246         }
247
248         Update_flags |= UF_WORLD_CHANGED;
249
250         return  1;
251 }
252
253 int TexSlideDown()
254 {
255         return DoTexSlideDown(3);
256 }
257
258 int TexSlideDownBig()
259 {
260         return DoTexSlideDown(1);
261 }
262
263 //      -----------------------------------------------------------
264 //      Compute the center of the side in u,v coordinates.
265 void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum)
266 {
267         int     v;
268         side    *sidep = &segp->sides[sidenum];
269
270         uvcenter->u = 0;
271         uvcenter->v = 0;
272
273         for (v=0; v<4; v++) {
274                 uvcenter->u += sidep->uvls[v].u;
275                 uvcenter->v += sidep->uvls[v].v;
276         }
277
278         uvcenter->u /= 4;
279         uvcenter->v /= 4;
280 }
281
282
283 //      -----------------------------------------------------------
284 //      rotate point *uv by matrix rotmat, return *uvrot
285 void rotate_uv_point(uvl *uvrot, fix *rotmat, uvl *uv, uvl *uvcenter)
286 {
287         uvrot->u = fixmul(uv->u - uvcenter->u,rotmat[0]) + fixmul(uv->v - uvcenter->v,rotmat[1]) + uvcenter->u;
288         uvrot->v = fixmul(uv->u - uvcenter->u,rotmat[2]) + fixmul(uv->v - uvcenter->v,rotmat[3]) + uvcenter->v;
289 }
290
291 //      -----------------------------------------------------------
292 //      Compute the center of the side in u,v coordinates.
293 void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter)
294 {
295         int     v;
296         side    *sidep = &segp->sides[sidenum];
297         uvl     tuv;
298
299         for (v=0; v<4; v++) {
300                 rotate_uv_point(&tuv, rotmat, &sidep->uvls[v], uvcenter);
301                 sidep->uvls[v] = tuv;
302         }
303 }
304
305 //      -----------------------------------------------------------
306 //      ang is in 0..ffff = 0..359.999 degrees
307 //      rotmat is filled in with 4 fixes
308 void create_2d_rotation_matrix(fix *rotmat, fix ang)
309 {
310         fix     sinang, cosang;
311
312         fix_sincos(ang, &sinang, &cosang);
313
314         rotmat[0] = cosang;
315         rotmat[1] = sinang;
316         rotmat[2] = -sinang;
317         rotmat[3] = cosang;
318         
319 }
320
321
322 //      -----------------------------------------------------------
323 int DoTexRotateLeft(int value)
324 {
325         uvl     uvcenter;
326         fix     rotmat[4];
327
328         compute_uv_side_center(&uvcenter, Cursegp, Curside);
329
330         //      Create a rotation matrix
331         create_2d_rotation_matrix(rotmat, -F1_0/value);
332
333         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
334
335         Update_flags |= UF_WORLD_CHANGED;
336
337         return  1;
338 }
339
340 int TexRotateLeft()
341 {
342         return DoTexRotateLeft(192);
343 }
344
345 int TexRotateLeftBig()
346 {
347         return DoTexRotateLeft(64);
348 }
349
350
351 //      -----------------------------------------------------------
352 int DoTexSlideRight(int value)
353 {
354         side    *sidep;
355         uvl     duvl03;
356         fix     dist;
357         sbyte   *vp;
358         int     v;
359
360         vp = Side_to_verts[Curside];
361         sidep = &Cursegp->sides[Curside];
362
363         dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]);
364         dist *= value;
365         if (dist < F1_0/(64*value))
366                 dist = F1_0/(64*value);
367
368         duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist);
369         duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist);
370
371         for (v=0; v<4; v++) {
372                 sidep->uvls[v].u += duvl03.u;
373                 sidep->uvls[v].v += duvl03.v;
374         }
375
376         Update_flags |= UF_WORLD_CHANGED;
377
378         return  1;
379 }
380
381 int TexSlideRight()
382 {
383         return DoTexSlideRight(3);
384 }
385
386 int TexSlideRightBig()
387 {
388         return DoTexSlideRight(1);
389 }
390
391 //      -----------------------------------------------------------
392 int DoTexRotateRight(int value)
393 {
394         uvl     uvcenter;
395         fix     rotmat[4];
396
397         compute_uv_side_center(&uvcenter, Cursegp, Curside);
398
399         //      Create a rotation matrix
400         create_2d_rotation_matrix(rotmat, F1_0/value);
401
402         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
403
404         Update_flags |= UF_WORLD_CHANGED;
405
406         return  1;
407 }
408
409 int TexRotateRight()
410 {
411         return DoTexRotateRight(192);
412 }
413
414 int TexRotateRightBig()
415 {
416         return DoTexRotateRight(64);
417 }
418
419 //      -----------------------------------------------------------
420 int     TexSelectActiveEdge()
421 {
422         return  1;
423 }
424
425 //      -----------------------------------------------------------
426 int     TexRotate90Degrees()
427 {
428         uvl     uvcenter;
429         fix     rotmat[4];
430
431         compute_uv_side_center(&uvcenter, Cursegp, Curside);
432
433         //      Create a rotation matrix
434         create_2d_rotation_matrix(rotmat, F1_0/4);
435
436         rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter);
437
438         Update_flags |= UF_WORLD_CHANGED;
439
440         return  1;
441 }
442
443 //      -----------------------------------------------------------
444 int     TexSetDefault()
445 {
446         Num_tilings = 1;
447
448         Stretch_scale_x = F1_0;
449         Stretch_scale_y = F1_0;
450
451         assign_default_uvs_to_side(Cursegp,Curside);
452
453         Update_flags |= UF_GAME_VIEW_CHANGED;
454         return  1;
455 }
456
457 //      -----------------------------------------------------------
458 int     TexIncreaseTiling()
459 {
460
461         Num_tilings++;
462         assign_default_uvs_to_side(Cursegp, Curside);
463         Update_flags |= UF_GAME_VIEW_CHANGED;
464
465         return  1;
466 }
467
468 //      -----------------------------------------------------------
469 int     TexDecreaseTiling()
470 {
471
472         if (--Num_tilings < 1)
473                 Num_tilings = 1;
474
475         assign_default_uvs_to_side(Cursegp, Curside);
476         Update_flags |= UF_GAME_VIEW_CHANGED;
477
478         return  1;
479 }
480
481
482 //      direction = -1 or 1 depending on direction
483 int     TexStretchCommon(int direction)
484 {
485         fix     *sptr;
486
487         if ((Curedge == 0) || (Curedge == 2))
488                 sptr = &Stretch_scale_x;
489         else
490                 sptr = &Stretch_scale_y;
491
492         *sptr += direction*F1_0/64;
493
494         if (*sptr < F1_0/16)
495                 *sptr = F1_0/16;
496
497         if (*sptr > 2*F1_0)
498                 *sptr = 2*F1_0;
499
500         stretch_uvs_from_curedge(Cursegp, Curside);
501
502         editor_status("Stretch scale = %7.4f, use Set Default to return to 1.0", f2fl(*sptr));
503
504         Update_flags |= UF_GAME_VIEW_CHANGED;
505         return  1;
506
507 }
508
509 int     TexStretchDown(void)
510 {
511         return TexStretchCommon(-1);
512
513 }
514
515 int     TexStretchUp(void)
516 {
517         return TexStretchCommon(1);
518
519 }
520