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 | } |