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