Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Portions of this file are copyright Rebirth contributors and licensed as
3
 * described in COPYING.txt.
4
 * Portions of this file are copyright Parallax Software and licensed
5
 * according to the Parallax license below.
6
 * See COPYING.txt for license details.
7
 
8
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17
COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
/*
21
 *
22
 * Texture map assignment.
23
 *
24
 */
25
 
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <stdarg.h>
29
#include <math.h>
30
#include <string.h>
31
#include "inferno.h"
32
#include "segment.h"
33
#include "seguvs.h"
34
#include "editor.h"
35
#include "editor/esegment.h"
36
#include "maths.h"
37
#include "dxxerror.h"
38
#include "kdefs.h"
39
 
40
#include "compiler-range_for.h"
41
 
42
static uvl compute_uv_side_center(const unique_segment &segp, sidenum_fast_t sidenum);
43
static void rotate_uv_points_on_side(unique_segment &segp, sidenum_fast_t sidenum, const std::array<fix, 4> &rotmat, const uvl &uvcenter);
44
 
45
//      -----------------------------------------------------------
46
int     TexFlipX()
47
{
48
        const auto uvcenter = compute_uv_side_center(Cursegp, Curside);
49
        std::array<fix, 4> rotmat;
50
        //      Create a rotation matrix
51
        rotmat[0] = -0xffff;
52
        rotmat[1] = 0;
53
        rotmat[2] = 0;
54
        rotmat[3] = 0xffff;
55
 
56
        rotate_uv_points_on_side(Cursegp, Curside, rotmat, uvcenter);
57
 
58
        Update_flags |= UF_WORLD_CHANGED;
59
 
60
        return  1;
61
}
62
 
63
//      -----------------------------------------------------------
64
int     TexFlipY()
65
{
66
        const auto uvcenter = compute_uv_side_center(Cursegp, Curside);
67
        std::array<fix, 4> rotmat;
68
        //      Create a rotation matrix
69
        rotmat[0] = 0xffff;
70
        rotmat[1] = 0;
71
        rotmat[2] = 0;
72
        rotmat[3] = -0xffff;
73
 
74
        rotate_uv_points_on_side(Cursegp, Curside, rotmat, uvcenter);
75
 
76
        Update_flags |= UF_WORLD_CHANGED;
77
 
78
        return  1;
79
}
80
 
81
//      -----------------------------------------------------------
82
static int DoTexSlideLeft(int value)
83
{
84
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
85
        auto &Vertices = LevelSharedVertexState.get_vertices();
86
        uvl     duvl03;
87
        fix     dist;
88
        auto &vp = Side_to_verts[Curside];
89
        auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
90
 
91
        auto &vcvertptr = Vertices.vcptr;
92
        dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[3]]), vcvertptr(Cursegp->verts[vp[0]]));
93
        dist *= value;
94
        if (dist < F1_0/(64*value))
95
                dist = F1_0/(64*value);
96
 
97
        duvl03.u = fixdiv(uvls[3].u - uvls[0].u,dist);
98
        duvl03.v = fixdiv(uvls[3].v - uvls[0].v,dist);
99
 
100
        range_for (auto &v, uvls)
101
        {
102
                v.u -= duvl03.u;
103
                v.v -= duvl03.v;
104
        }
105
 
106
        Update_flags |= UF_WORLD_CHANGED;
107
 
108
        return  1;
109
}
110
 
111
int TexSlideLeft()
112
{
113
        return DoTexSlideLeft(3);
114
}
115
 
116
int TexSlideLeftBig()
117
{
118
        return DoTexSlideLeft(1);
119
}
120
 
121
//      -----------------------------------------------------------
122
static int DoTexSlideUp(int value)
123
{
124
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
125
        auto &Vertices = LevelSharedVertexState.get_vertices();
126
        uvl     duvl03;
127
        fix     dist;
128
        auto &vp = Side_to_verts[Curside];
129
        auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
130
 
131
        auto &vcvertptr = Vertices.vcptr;
132
        dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[1]]), vcvertptr(Cursegp->verts[vp[0]]));
133
        dist *= value;
134
 
135
        if (dist < F1_0/(64*value))
136
                dist = F1_0/(64*value);
137
 
138
        duvl03.u = fixdiv(uvls[1].u - uvls[0].u,dist);
139
        duvl03.v = fixdiv(uvls[1].v - uvls[0].v,dist);
140
 
141
        range_for (auto &v, uvls)
142
        {
143
                v.u -= duvl03.u;
144
                v.v -= duvl03.v;
145
        }
146
 
147
        Update_flags |= UF_WORLD_CHANGED;
148
 
149
        return  1;
150
}
151
 
152
int TexSlideUp()
153
{
154
        return DoTexSlideUp(3);
155
}
156
 
157
int TexSlideUpBig()
158
{
159
        return DoTexSlideUp(1);
160
}
161
 
162
 
163
//      -----------------------------------------------------------
164
static int DoTexSlideDown(int value)
165
{
166
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
167
        auto &Vertices = LevelSharedVertexState.get_vertices();
168
        uvl     duvl03;
169
        fix     dist;
170
        auto &vp = Side_to_verts[Curside];
171
        auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
172
 
173
        auto &vcvertptr = Vertices.vcptr;
174
        dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[1]]), vcvertptr(Cursegp->verts[vp[0]]));
175
        dist *= value;
176
        if (dist < F1_0/(64*value))
177
                dist = F1_0/(64*value);
178
 
179
        duvl03.u = fixdiv(uvls[1].u - uvls[0].u,dist);
180
        duvl03.v = fixdiv(uvls[1].v - uvls[0].v,dist);
181
 
182
        range_for (auto &v, uvls)
183
        {
184
                v.u += duvl03.u;
185
                v.v += duvl03.v;
186
        }
187
 
188
        Update_flags |= UF_WORLD_CHANGED;
189
 
190
        return  1;
191
}
192
 
193
int TexSlideDown()
194
{
195
        return DoTexSlideDown(3);
196
}
197
 
198
int TexSlideDownBig()
199
{
200
        return DoTexSlideDown(1);
201
}
202
 
203
//      -----------------------------------------------------------
204
//      Compute the center of the side in u,v coordinates.
205
static uvl compute_uv_side_center(const unique_segment &segp, const sidenum_fast_t sidenum)
206
{
207
        uvl uvcenter{};
208
        range_for (auto &v, segp.sides[sidenum].uvls)
209
        {
210
                uvcenter.u += v.u;
211
                uvcenter.v += v.v;
212
        }
213
        uvcenter.u /= 4;
214
        uvcenter.v /= 4;
215
        return uvcenter;
216
}
217
 
218
//      -----------------------------------------------------------
219
//      rotate point *uv by matrix rotmat, return *uvrot
220
static uvl rotate_uv_point(const std::array<fix, 4> &rotmat, const uvl &uv, const uvl &uvcenter)
221
{
222
        const auto centered_u = uv.u - uvcenter.u;
223
        const auto centered_v = uv.v - uvcenter.v;
224
        return {
225
                fixmul(centered_u, rotmat[0]) + fixmul(centered_v, rotmat[1]) + uvcenter.u,
226
                fixmul(centered_u, rotmat[2]) + fixmul(centered_v, rotmat[3]) + uvcenter.v,
227
 
228
        };
229
}
230
 
231
//      -----------------------------------------------------------
232
//      Compute the center of the side in u,v coordinates.
233
static void rotate_uv_points_on_side(unique_segment &segp, const sidenum_fast_t sidenum, const std::array<fix, 4> &rotmat, const uvl &uvcenter)
234
{
235
        range_for (auto &v, segp.sides[sidenum].uvls)
236
        {
237
                v = rotate_uv_point(rotmat, v, uvcenter);
238
        }
239
}
240
 
241
//      -----------------------------------------------------------
242
//      ang is in 0..ffff = 0..359.999 degrees
243
//      rotmat is filled in with 4 fixes
244
static std::array<fix, 4> create_2d_rotation_matrix(fix ang)
245
{
246
        const auto &&a = fix_sincos(ang);
247
        const auto &sinang = a.sin;
248
        const auto &cosang = a.cos;
249
        return {{
250
                cosang,
251
                sinang,
252
                -sinang,
253
                cosang
254
        }};
255
}
256
 
257
 
258
//      -----------------------------------------------------------
259
static int DoTexRotateLeft(int value)
260
{
261
        const auto uvcenter = compute_uv_side_center(Cursegp, Curside);
262
        //      Create a rotation matrix
263
        const auto rotmat = create_2d_rotation_matrix(-F1_0/value);
264
 
265
        rotate_uv_points_on_side(Cursegp, Curside, rotmat, uvcenter);
266
 
267
        Update_flags |= UF_WORLD_CHANGED;
268
 
269
        return  1;
270
}
271
 
272
int TexRotateLeft()
273
{
274
        return DoTexRotateLeft(192);
275
}
276
 
277
int TexRotateLeftBig()
278
{
279
        return DoTexRotateLeft(64);
280
}
281
 
282
 
283
//      -----------------------------------------------------------
284
static int DoTexSlideRight(int value)
285
{
286
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
287
        auto &Vertices = LevelSharedVertexState.get_vertices();
288
        uvl     duvl03;
289
        fix     dist;
290
        auto &vp = Side_to_verts[Curside];
291
        auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
292
 
293
        auto &vcvertptr = Vertices.vcptr;
294
        dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[3]]), vcvertptr(Cursegp->verts[vp[0]]));
295
        dist *= value;
296
        if (dist < F1_0/(64*value))
297
                dist = F1_0/(64*value);
298
 
299
        duvl03.u = fixdiv(uvls[3].u - uvls[0].u,dist);
300
        duvl03.v = fixdiv(uvls[3].v - uvls[0].v,dist);
301
 
302
        range_for (auto &v, uvls)
303
        {
304
                v.u += duvl03.u;
305
                v.v += duvl03.v;
306
        }
307
 
308
        Update_flags |= UF_WORLD_CHANGED;
309
 
310
        return  1;
311
}
312
 
313
int TexSlideRight()
314
{
315
        return DoTexSlideRight(3);
316
}
317
 
318
int TexSlideRightBig()
319
{
320
        return DoTexSlideRight(1);
321
}
322
 
323
//      -----------------------------------------------------------
324
static int DoTexRotateRight(int value)
325
{
326
        const auto uvcenter = compute_uv_side_center(Cursegp, Curside);
327
 
328
        //      Create a rotation matrix
329
        const auto rotmat = create_2d_rotation_matrix(F1_0/value);
330
 
331
        rotate_uv_points_on_side(Cursegp, Curside, rotmat, uvcenter);
332
 
333
        Update_flags |= UF_WORLD_CHANGED;
334
 
335
        return  1;
336
}
337
 
338
int TexRotateRight()
339
{
340
        return DoTexRotateRight(192);
341
}
342
 
343
int TexRotateRightBig()
344
{
345
        return DoTexRotateRight(64);
346
}
347
 
348
//      -----------------------------------------------------------
349
int     TexSelectActiveEdge()
350
{
351
        return  1;
352
}
353
 
354
//      -----------------------------------------------------------
355
int     TexRotate90Degrees()
356
{
357
        const auto uvcenter = compute_uv_side_center(Cursegp, Curside);
358
 
359
        //      Create a rotation matrix
360
        const auto rotmat = create_2d_rotation_matrix(F1_0/4);
361
 
362
        rotate_uv_points_on_side(Cursegp, Curside, rotmat, uvcenter);
363
 
364
        Update_flags |= UF_WORLD_CHANGED;
365
 
366
        return  1;
367
}
368
 
369
//      -----------------------------------------------------------
370
int     TexSetDefault()
371
{
372
        Num_tilings = 1;
373
 
374
        Stretch_scale_x = F1_0;
375
        Stretch_scale_y = F1_0;
376
 
377
        assign_default_uvs_to_side(Cursegp,Curside);
378
 
379
        Update_flags |= UF_GAME_VIEW_CHANGED;
380
        return  1;
381
}
382
 
383
//      -----------------------------------------------------------
384
int     TexIncreaseTiling()
385
{
386
 
387
        Num_tilings++;
388
        assign_default_uvs_to_side(Cursegp, Curside);
389
        Update_flags |= UF_GAME_VIEW_CHANGED;
390
 
391
        return  1;
392
}
393
 
394
//      -----------------------------------------------------------
395
int     TexDecreaseTiling()
396
{
397
 
398
        if (--Num_tilings < 1)
399
                Num_tilings = 1;
400
 
401
        assign_default_uvs_to_side(Cursegp, Curside);
402
        Update_flags |= UF_GAME_VIEW_CHANGED;
403
 
404
        return  1;
405
}
406
 
407
 
408
//      direction = -1 or 1 depending on direction
409
static int      TexStretchCommon(int direction)
410
{
411
        fix     *sptr;
412
 
413
        if ((Curedge == 0) || (Curedge == 2))
414
                sptr = &Stretch_scale_x;
415
        else
416
                sptr = &Stretch_scale_y;
417
 
418
        *sptr += direction*F1_0/64;
419
 
420
        if (*sptr < F1_0/16)
421
                *sptr = F1_0/16;
422
 
423
        if (*sptr > 2*F1_0)
424
                *sptr = 2*F1_0;
425
 
426
        stretch_uvs_from_curedge(Cursegp, Curside);
427
 
428
        editor_status_fmt("Stretch scale = %7.4f, use Set Default to return to 1.0", f2fl(*sptr));
429
 
430
        Update_flags |= UF_GAME_VIEW_CHANGED;
431
        return  1;
432
 
433
}
434
 
435
int     TexStretchDown(void)
436
{
437
        return TexStretchCommon(-1);
438
 
439
}
440
 
441
int     TexStretchUp(void)
442
{
443
        return TexStretchCommon(1);
444
 
445
}
446