2006-03-20 17:12:09 +00:00
|
|
|
/*
|
2018-09-02 00:57:29 +00:00
|
|
|
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
2014-06-12 08:41:03 +00:00
|
|
|
* It is copyright by its individual contributors, as recorded in the
|
|
|
|
* project's Git history. See COPYING.txt at the top level for license
|
|
|
|
* terms and a link to the Git history.
|
|
|
|
*/
|
2006-03-20 17:12:09 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Rod routines
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "3d.h"
|
|
|
|
#include "globvars.h"
|
2012-07-01 02:54:33 +00:00
|
|
|
#include "maths.h"
|
2016-09-24 18:06:11 +00:00
|
|
|
#if !DXX_USE_OGL
|
2015-02-07 05:59:27 +00:00
|
|
|
#include "gr.h"
|
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-09-28 22:16:29 +00:00
|
|
|
#include "compiler-range_for.h"
|
|
|
|
|
2015-12-13 18:00:49 +00:00
|
|
|
namespace dcx {
|
2015-12-05 22:57:24 +00:00
|
|
|
|
2015-08-12 03:11:46 +00:00
|
|
|
namespace {
|
|
|
|
|
2013-11-28 00:24:27 +00:00
|
|
|
struct rod_4point
|
|
|
|
{
|
2020-05-02 21:18:42 +00:00
|
|
|
std::array<cg3s_point *, 4> point_list;
|
|
|
|
std::array<g3s_point, 4> points;
|
2013-11-28 00:24:27 +00:00
|
|
|
};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
//compute the corners of a rod. fills in vertbuf.
|
2014-11-13 03:34:35 +00:00
|
|
|
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)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
//compute vector from one point to other, do cross product with vector
|
|
|
|
//from eye to get perpendiclar
|
|
|
|
|
2014-11-13 03:34:35 +00:00
|
|
|
auto delta_vec = vm_vec_sub(bot_point.p3_vec,top_point.p3_vec);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
//unscale for aspect
|
|
|
|
|
|
|
|
delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x);
|
|
|
|
delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y);
|
|
|
|
|
|
|
|
//calc perp vector
|
|
|
|
|
|
|
|
//do lots of normalizing to prevent overflowing. When this code works,
|
|
|
|
//it should be optimized
|
|
|
|
|
2014-09-28 21:11:03 +00:00
|
|
|
vm_vec_normalize(delta_vec);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-11-13 03:34:35 +00:00
|
|
|
const auto top = vm_vec_normalized(top_point.p3_vec);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-11-02 03:44:12 +00:00
|
|
|
auto rod_norm = vm_vec_cross(delta_vec,top);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-09-28 21:11:03 +00:00
|
|
|
vm_vec_normalize(rod_norm);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
//scale for aspect
|
|
|
|
|
|
|
|
rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x);
|
|
|
|
rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y);
|
|
|
|
|
|
|
|
//now we have the usable edge. generate four points
|
|
|
|
|
|
|
|
//top points
|
|
|
|
|
2014-11-02 03:43:47 +00:00
|
|
|
auto tempv = vm_vec_copy_scale(rod_norm,top_width);
|
2006-03-20 17:12:09 +00:00
|
|
|
tempv.z = 0;
|
|
|
|
|
2013-11-28 00:24:27 +00:00
|
|
|
rod_point_group.point_list[0] = &rod_point_group.points[0];
|
|
|
|
rod_point_group.point_list[1] = &rod_point_group.points[1];
|
|
|
|
rod_point_group.point_list[2] = &rod_point_group.points[2];
|
|
|
|
rod_point_group.point_list[3] = &rod_point_group.points[3];
|
2015-04-19 04:18:49 +00:00
|
|
|
auto &rod_points = rod_point_group.points;
|
2014-11-13 03:34:35 +00:00
|
|
|
vm_vec_add(rod_points[0].p3_vec,top_point.p3_vec,tempv);
|
|
|
|
vm_vec_sub(rod_points[1].p3_vec,top_point.p3_vec,tempv);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-09-28 21:43:14 +00:00
|
|
|
vm_vec_copy_scale(tempv,rod_norm,bot_width);
|
2006-03-20 17:12:09 +00:00
|
|
|
tempv.z = 0;
|
|
|
|
|
2014-11-13 03:34:35 +00:00
|
|
|
vm_vec_sub(rod_points[2].p3_vec,bot_point.p3_vec,tempv);
|
|
|
|
vm_vec_add(rod_points[3].p3_vec,bot_point.p3_vec,tempv);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
//now code the four points
|
|
|
|
|
2014-09-28 22:16:29 +00:00
|
|
|
ubyte codes_and = 0xff;
|
|
|
|
range_for (auto &i, rod_points)
|
2017-08-26 19:47:51 +00:00
|
|
|
{
|
2014-11-13 03:16:17 +00:00
|
|
|
codes_and &= g3_code_point(i);
|
2006-03-20 17:12:09 +00:00
|
|
|
//clear flags for new points (not projected)
|
2022-10-02 19:51:35 +00:00
|
|
|
i.p3_flags = {};
|
2017-08-26 19:47:51 +00:00
|
|
|
}
|
|
|
|
return codes_and;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2020-12-26 21:17:29 +00:00
|
|
|
}
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
//draw a bitmap object that is always facing you
|
|
|
|
//returns 1 if off screen, 0 if drew
|
2017-02-11 21:42:40 +00:00
|
|
|
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)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2013-11-28 00:24:27 +00:00
|
|
|
rod_4point rod;
|
2014-11-13 03:34:42 +00:00
|
|
|
if (calc_rod_corners(rod,bot_point,bot_width,top_point,top_width))
|
2014-08-12 02:58:46 +00:00
|
|
|
return;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-09-04 03:02:21 +00:00
|
|
|
const fix average_light = static_cast<unsigned>(light.r+light.g+light.b)/3;
|
2020-05-02 21:18:42 +00:00
|
|
|
const std::array<g3s_uvl, 4> uvl_list{{
|
2014-09-04 03:02:21 +00:00
|
|
|
{ 0x0200, 0x0200, average_light },
|
|
|
|
{ 0xfe00, 0x0200, average_light },
|
|
|
|
{ 0xfe00, 0xfe00, average_light },
|
|
|
|
{ 0x0200, 0xfe00, average_light }
|
|
|
|
}};
|
2020-05-02 21:18:42 +00:00
|
|
|
const std::array<g3s_lrgb, 4> lrgb_list{{
|
2014-07-01 03:10:56 +00:00
|
|
|
light,
|
|
|
|
light,
|
|
|
|
light,
|
|
|
|
light,
|
2014-09-04 03:02:21 +00:00
|
|
|
}};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-02-11 21:42:40 +00:00
|
|
|
g3_draw_tmap(canvas, rod.point_list, uvl_list, lrgb_list, bitmap);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if !DXX_USE_OGL
|
2006-03-20 17:12:09 +00:00
|
|
|
//draws a bitmap with the specified 3d width & height
|
|
|
|
//returns 1 if off screen, 0 if drew
|
2017-02-11 21:42:42 +00:00
|
|
|
void g3_draw_bitmap(grs_canvas &canvas, const vms_vector &pos, fix width, fix height, grs_bitmap &bm)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
g3s_point pnt;
|
2014-08-12 03:01:05 +00:00
|
|
|
fix w,h;
|
2014-10-02 03:02:35 +00:00
|
|
|
if (g3_rotate_point(pnt,pos) & CC_BEHIND)
|
2015-04-02 02:36:54 +00:00
|
|
|
return;
|
2014-11-13 03:21:33 +00:00
|
|
|
g3_project_point(pnt);
|
2022-10-02 19:51:35 +00:00
|
|
|
if (pnt.p3_flags & projection_flag::overflow)
|
2015-04-02 02:36:54 +00:00
|
|
|
return;
|
2014-08-12 03:01:05 +00:00
|
|
|
#ifndef __powerc
|
2022-05-24 02:32:58 +00:00
|
|
|
const auto pz = pnt.p3_z;
|
|
|
|
if (const auto ox = checkmuldiv(width, Canv_w2, pz))
|
|
|
|
w = fixmul(*ox, Matrix_scale.x);
|
2006-03-20 17:12:09 +00:00
|
|
|
else
|
2015-04-02 02:36:54 +00:00
|
|
|
return;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2022-05-24 02:32:58 +00:00
|
|
|
if (const auto oy = checkmuldiv(height, Canv_h2, pz))
|
|
|
|
h = fixmul(*oy, Matrix_scale.y);
|
2006-03-20 17:12:09 +00:00
|
|
|
else
|
2015-04-02 02:36:54 +00:00
|
|
|
return;
|
2006-03-20 17:12:09 +00:00
|
|
|
#else
|
|
|
|
if (pnt.p3_z == 0)
|
2015-04-02 02:36:54 +00:00
|
|
|
return;
|
2014-08-12 03:01:05 +00:00
|
|
|
double fz = f2fl(pnt.p3_z);
|
2006-03-20 17:12:09 +00:00
|
|
|
w = fixmul(fl2f(((f2fl(width)*fCanv_w2) / fz)), Matrix_scale.x);
|
|
|
|
h = fixmul(fl2f(((f2fl(height)*fCanv_h2) / fz)), Matrix_scale.y);
|
2014-08-12 03:01:05 +00:00
|
|
|
#endif
|
2015-02-19 03:20:52 +00:00
|
|
|
const fix blob0y = pnt.p3_sy - h, blob1x = pnt.p3_sx + w;
|
2020-05-02 21:18:42 +00:00
|
|
|
const std::array<grs_point, 3> blob_vertices{{
|
2015-02-19 03:20:52 +00:00
|
|
|
{pnt.p3_sx - w, blob0y},
|
|
|
|
{blob1x, blob0y},
|
|
|
|
{blob1x, pnt.p3_sy + h},
|
2014-11-21 03:34:50 +00:00
|
|
|
}};
|
2017-02-11 21:42:42 +00:00
|
|
|
scale_bitmap(bm, blob_vertices, 0, canvas.cv_bitmap);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-12-05 22:57:24 +00:00
|
|
|
}
|