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