Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
3
 * It is copyright by its individual contributors, as recorded in the
4
 * project's Git history.  See COPYING.txt at the top level for license
5
 * terms and a link to the Git history.
6
 */
7
/*
8
 *
9
 * Rod routines
10
 *
11
 */
12
 
13
 
14
#include "3d.h"
15
#include "globvars.h"
16
#include "maths.h"
17
#if !DXX_USE_OGL
18
#include "gr.h"
19
#endif
20
 
21
#include "compiler-range_for.h"
22
 
23
namespace dcx {
24
 
25
namespace {
26
 
27
struct rod_4point
28
{
29
        std::array<cg3s_point *, 4> point_list;
30
        std::array<g3s_point, 4> points;
31
};
32
 
33
}
34
 
35
//compute the corners of a rod.  fills in vertbuf.
36
static int calc_rod_corners(rod_4point &rod_point_group, const g3s_point &bot_point,fix bot_width,const g3s_point &top_point,fix top_width)
37
{
38
        //compute vector from one point to other, do cross product with vector
39
        //from eye to get perpendiclar
40
 
41
        auto delta_vec = vm_vec_sub(bot_point.p3_vec,top_point.p3_vec);
42
 
43
        //unscale for aspect
44
 
45
        delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x);
46
        delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y);
47
 
48
        //calc perp vector
49
 
50
        //do lots of normalizing to prevent overflowing.  When this code works,
51
        //it should be optimized
52
 
53
        vm_vec_normalize(delta_vec);
54
 
55
        const auto top = vm_vec_normalized(top_point.p3_vec);
56
 
57
        auto rod_norm = vm_vec_cross(delta_vec,top);
58
 
59
        vm_vec_normalize(rod_norm);
60
 
61
        //scale for aspect
62
 
63
        rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x);
64
        rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y);
65
 
66
        //now we have the usable edge.  generate four points
67
 
68
        //top points
69
 
70
        auto tempv = vm_vec_copy_scale(rod_norm,top_width);
71
        tempv.z = 0;
72
 
73
        rod_point_group.point_list[0] = &rod_point_group.points[0];
74
        rod_point_group.point_list[1] = &rod_point_group.points[1];
75
        rod_point_group.point_list[2] = &rod_point_group.points[2];
76
        rod_point_group.point_list[3] = &rod_point_group.points[3];
77
        auto &rod_points = rod_point_group.points;
78
        vm_vec_add(rod_points[0].p3_vec,top_point.p3_vec,tempv);
79
        vm_vec_sub(rod_points[1].p3_vec,top_point.p3_vec,tempv);
80
 
81
        vm_vec_copy_scale(tempv,rod_norm,bot_width);
82
        tempv.z = 0;
83
 
84
        vm_vec_sub(rod_points[2].p3_vec,bot_point.p3_vec,tempv);
85
        vm_vec_add(rod_points[3].p3_vec,bot_point.p3_vec,tempv);
86
 
87
 
88
        //now code the four points
89
 
90
        ubyte codes_and = 0xff;
91
        range_for (auto &i, rod_points)
92
        {
93
                codes_and &= g3_code_point(i);
94
        //clear flags for new points (not projected)
95
                i.p3_flags = 0;
96
        }
97
        return codes_and;
98
}
99
 
100
//draw a bitmap object that is always facing you
101
//returns 1 if off screen, 0 if drew
102
void g3_draw_rod_tmap(grs_canvas &canvas, grs_bitmap &bitmap, const g3s_point &bot_point, fix bot_width, const g3s_point &top_point, fix top_width, g3s_lrgb light)
103
{
104
        rod_4point rod;
105
        if (calc_rod_corners(rod,bot_point,bot_width,top_point,top_width))
106
                return;
107
 
108
        const fix average_light = static_cast<unsigned>(light.r+light.g+light.b)/3;
109
        const std::array<g3s_uvl, 4> uvl_list{{
110
                { 0x0200, 0x0200, average_light },
111
                { 0xfe00, 0x0200, average_light },
112
                { 0xfe00, 0xfe00, average_light },
113
                { 0x0200, 0xfe00, average_light }
114
        }};
115
        const std::array<g3s_lrgb, 4> lrgb_list{{
116
                light,
117
                light,
118
                light,
119
                light,
120
        }};
121
 
122
        g3_draw_tmap(canvas, rod.point_list, uvl_list, lrgb_list, bitmap);
123
}
124
 
125
#if !DXX_USE_OGL
126
//draws a bitmap with the specified 3d width & height 
127
//returns 1 if off screen, 0 if drew
128
void g3_draw_bitmap(grs_canvas &canvas, const vms_vector &pos, fix width, fix height, grs_bitmap &bm)
129
{
130
        g3s_point pnt;
131
        fix w,h;
132
        if (g3_rotate_point(pnt,pos) & CC_BEHIND)
133
                return;
134
        g3_project_point(pnt);
135
        if (pnt.p3_flags & PF_OVERFLOW)
136
                return;
137
#ifndef __powerc
138
        fix t;
139
        if (checkmuldiv(&t,width,Canv_w2,pnt.p3_z))
140
                w = fixmul(t,Matrix_scale.x);
141
        else
142
                return;
143
 
144
        if (checkmuldiv(&t,height,Canv_h2,pnt.p3_z))
145
                h = fixmul(t,Matrix_scale.y);
146
        else
147
                return;
148
#else
149
        if (pnt.p3_z == 0)
150
                return;
151
        double fz = f2fl(pnt.p3_z);
152
        w = fixmul(fl2f(((f2fl(width)*fCanv_w2) / fz)), Matrix_scale.x);
153
        h = fixmul(fl2f(((f2fl(height)*fCanv_h2) / fz)), Matrix_scale.y);
154
#endif
155
        const fix blob0y = pnt.p3_sy - h, blob1x = pnt.p3_sx + w;
156
        const std::array<grs_point, 3> blob_vertices{{
157
                {pnt.p3_sx - w, blob0y},
158
                {blob1x, blob0y},
159
                {blob1x, pnt.p3_sy + h},
160
        }};
161
        scale_bitmap(bm, blob_vertices, 0, canvas.cv_bitmap);
162
}
163
#endif
164
 
165
 
166
 
167
}