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