2006-03-20 17:12:09 +00:00
|
|
|
/*
|
2014-06-01 17:55:23 +00:00
|
|
|
* Portions of this file are copyright Rebirth contributors and licensed as
|
|
|
|
* described in COPYING.txt.
|
|
|
|
* Portions of this file are copyright Parallax Software and licensed
|
|
|
|
* according to the Parallax license below.
|
|
|
|
* See COPYING.txt for license details.
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
|
|
|
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
|
|
|
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
|
|
|
|
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
|
|
|
|
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
|
|
|
|
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
|
|
|
|
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
|
|
|
|
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
|
|
|
|
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
|
|
|
|
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Code to render cool external-scene terrain
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-09-28 21:09:27 +00:00
|
|
|
#include <bitset>
|
2006-03-20 17:12:09 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "3d.h"
|
2012-07-07 18:35:06 +00:00
|
|
|
#include "dxxerror.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
#include "gr.h"
|
|
|
|
#include "texmap.h"
|
|
|
|
#include "iff.h"
|
|
|
|
#include "u_mem.h"
|
|
|
|
#include "inferno.h"
|
|
|
|
#include "textures.h"
|
|
|
|
#include "object.h"
|
|
|
|
#include "endlevel.h"
|
|
|
|
#include "fireball.h"
|
|
|
|
#include "render.h"
|
2012-11-11 22:12:51 +00:00
|
|
|
#include "terrain.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-08-16 04:15:16 +00:00
|
|
|
#include "compiler-make_unique.h"
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
#define GRID_MAX_SIZE 64
|
|
|
|
#define GRID_SCALE i2f(2*20)
|
|
|
|
#define HEIGHT_SCALE f1_0
|
|
|
|
|
2014-09-28 21:09:27 +00:00
|
|
|
static int grid_w,grid_h;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-01-23 03:55:04 +00:00
|
|
|
static RAIIdmem<ubyte[]> height_array;
|
2014-07-22 03:11:56 +00:00
|
|
|
static std::unique_ptr<uint8_t[]> light_array;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
#define HEIGHT(_i,_j) (height_array[(_i)*grid_w+(_j)])
|
|
|
|
#define LIGHT(_i,_j) light_array[(_i)*grid_w+(_j)]
|
|
|
|
|
|
|
|
//!!#define HEIGHT(_i,_j) height_array[(grid_h-1-j)*grid_w+(_i)]
|
|
|
|
//!!#define LIGHT(_i,_j) light_array[(grid_h-1-j)*grid_w+(_i)]
|
|
|
|
|
2016-09-04 00:02:51 +00:00
|
|
|
#define LIGHTVAL(_i,_j) (static_cast<fix>(LIGHT(_i, _j)) << 8)
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-09-28 21:09:27 +00:00
|
|
|
static grs_bitmap *terrain_bm;
|
|
|
|
static int terrain_outline=0;
|
|
|
|
static int org_i,org_j;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// LINT: adding function prototypes
|
2013-09-22 22:26:27 +00:00
|
|
|
static void build_light_table(void);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
2017-03-11 19:56:26 +00:00
|
|
|
static void draw_cell(grs_canvas &canvas, const int i, const int j, cg3s_point &p0, cg3s_point &p1, cg3s_point &p2, cg3s_point &p3, int &mine_tiles_drawn)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2014-11-16 19:14:51 +00:00
|
|
|
array<cg3s_point *, 3> pointlist;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
pointlist[0] = &p0;
|
|
|
|
pointlist[1] = &p1;
|
|
|
|
pointlist[2] = &p3;
|
2014-09-04 03:02:21 +00:00
|
|
|
array<g3s_lrgb, 3> lrgb_list1;
|
|
|
|
array<g3s_uvl, 3> uvl_list1;
|
2011-04-07 20:32:51 +00:00
|
|
|
lrgb_list1[0].r = lrgb_list1[0].g = lrgb_list1[0].b = uvl_list1[0].l = LIGHTVAL(i,j);
|
|
|
|
lrgb_list1[1].r = lrgb_list1[1].g = lrgb_list1[1].b = uvl_list1[1].l = LIGHTVAL(i,j+1);
|
|
|
|
lrgb_list1[2].r = lrgb_list1[2].g = lrgb_list1[2].b = uvl_list1[2].l = LIGHTVAL(i+1,j);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
uvl_list1[0].u = (i)*f1_0/4; uvl_list1[0].v = (j)*f1_0/4;
|
|
|
|
uvl_list1[1].u = (i)*f1_0/4; uvl_list1[1].v = (j+1)*f1_0/4;
|
|
|
|
uvl_list1[2].u = (i+1)*f1_0/4; uvl_list1[2].v = (j)*f1_0/4;
|
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
g3_check_and_draw_tmap(canvas, pointlist, uvl_list1, lrgb_list1, *terrain_bm);
|
2006-03-20 17:12:09 +00:00
|
|
|
if (terrain_outline) {
|
2017-11-01 02:01:21 +00:00
|
|
|
#if !DXX_USE_OGL
|
|
|
|
const int lsave = Lighting_on;
|
2006-03-20 17:12:09 +00:00
|
|
|
Lighting_on=0;
|
2017-11-01 02:01:21 +00:00
|
|
|
#endif
|
2016-02-12 04:02:28 +00:00
|
|
|
const uint8_t color = BM_XRGB(31, 0, 0);
|
2017-03-11 19:56:26 +00:00
|
|
|
g3_draw_line(canvas, *pointlist[0],*pointlist[1], color);
|
|
|
|
g3_draw_line(canvas, *pointlist[2],*pointlist[0], color);
|
2017-11-01 02:01:21 +00:00
|
|
|
#if !DXX_USE_OGL
|
2006-03-20 17:12:09 +00:00
|
|
|
Lighting_on=lsave;
|
2017-11-01 02:01:21 +00:00
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
pointlist[0] = &p1;
|
|
|
|
pointlist[1] = &p2;
|
2014-09-04 03:02:21 +00:00
|
|
|
array<g3s_uvl, 3> uvl_list2;
|
|
|
|
array<g3s_lrgb, 3> lrgb_list2;
|
2011-04-07 20:32:51 +00:00
|
|
|
lrgb_list2[0].r = lrgb_list2[0].g = lrgb_list2[0].b = uvl_list2[0].l = LIGHTVAL(i,j+1);
|
|
|
|
lrgb_list2[1].r = lrgb_list2[1].g = lrgb_list2[1].b = uvl_list2[1].l = LIGHTVAL(i+1,j+1);
|
|
|
|
lrgb_list2[2].r = lrgb_list2[2].g = lrgb_list2[2].b = uvl_list2[2].l = LIGHTVAL(i+1,j);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
uvl_list2[0].u = (i)*f1_0/4; uvl_list2[0].v = (j+1)*f1_0/4;
|
|
|
|
uvl_list2[1].u = (i+1)*f1_0/4; uvl_list2[1].v = (j+1)*f1_0/4;
|
|
|
|
uvl_list2[2].u = (i+1)*f1_0/4; uvl_list2[2].v = (j)*f1_0/4;
|
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
g3_check_and_draw_tmap(canvas, pointlist, uvl_list2, lrgb_list2, *terrain_bm);
|
2006-03-20 17:12:09 +00:00
|
|
|
if (terrain_outline) {
|
2017-11-01 02:01:21 +00:00
|
|
|
#if !DXX_USE_OGL
|
|
|
|
const int lsave = Lighting_on;
|
2006-03-20 17:12:09 +00:00
|
|
|
Lighting_on=0;
|
2017-11-01 02:01:21 +00:00
|
|
|
#endif
|
2016-02-12 04:02:28 +00:00
|
|
|
const uint8_t color = BM_XRGB(31, 0, 0);
|
2017-03-11 19:56:26 +00:00
|
|
|
g3_draw_line(canvas, *pointlist[0],*pointlist[1], color);
|
|
|
|
g3_draw_line(canvas, *pointlist[1],*pointlist[2], color);
|
|
|
|
g3_draw_line(canvas, *pointlist[2],*pointlist[0], color);
|
2017-11-01 02:01:21 +00:00
|
|
|
#if !DXX_USE_OGL
|
2006-03-20 17:12:09 +00:00
|
|
|
Lighting_on=lsave;
|
2017-11-01 02:01:21 +00:00
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i==org_i && j==org_j)
|
|
|
|
mine_tiles_drawn |= 1;
|
|
|
|
if (i==org_i-1 && j==org_j)
|
|
|
|
mine_tiles_drawn |= 2;
|
|
|
|
if (i==org_i && j==org_j-1)
|
|
|
|
mine_tiles_drawn |= 4;
|
|
|
|
if (i==org_i-1 && j==org_j-1)
|
|
|
|
mine_tiles_drawn |= 8;
|
|
|
|
|
|
|
|
if (mine_tiles_drawn == 0xf) {
|
|
|
|
//draw_exit_model();
|
|
|
|
mine_tiles_drawn=-1;
|
2015-05-05 03:20:42 +00:00
|
|
|
window_rendered_data window;
|
2017-03-11 19:56:26 +00:00
|
|
|
render_mine(canvas, exit_segnum, 0, window);
|
2006-03-20 17:12:09 +00:00
|
|
|
//if (ext_expl_playing)
|
|
|
|
// draw_fireball(&external_explosion);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-01-24 19:16:34 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
class terrain_y_cache
|
2014-09-28 21:09:27 +00:00
|
|
|
{
|
|
|
|
static const std::size_t cache_size = 256;
|
|
|
|
std::bitset<cache_size> yc_flags;
|
|
|
|
array<vms_vector, cache_size> y_cache;
|
2015-01-24 19:16:34 +00:00
|
|
|
public:
|
2014-10-02 03:02:36 +00:00
|
|
|
vms_vector &operator()(uint_fast32_t h);
|
2014-09-28 21:09:27 +00:00
|
|
|
};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-01-24 19:16:34 +00:00
|
|
|
}
|
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
vms_vector &terrain_y_cache::operator()(uint_fast32_t h)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2014-10-02 03:02:36 +00:00
|
|
|
auto &dyp = y_cache[h];
|
2017-09-30 18:00:15 +00:00
|
|
|
if (auto &&ycf = yc_flags[h])
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ycf = 1;
|
2014-11-02 03:43:47 +00:00
|
|
|
const auto tv = vm_vec_copy_scale(surface_orient.uvec,h*HEIGHT_SCALE);
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_rotate_delta_vec(dyp,tv);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2014-10-02 03:02:36 +00:00
|
|
|
return dyp;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
void render_terrain(grs_canvas &canvas, const vms_vector &org_point,int org_2dx,int org_2dy)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
vms_vector delta_i,delta_j; //delta_y;
|
2014-11-13 03:41:29 +00:00
|
|
|
g3s_point p,save_p_low,save_p_high;
|
2006-03-20 17:12:09 +00:00
|
|
|
g3s_point last_p2;
|
|
|
|
int i,j;
|
|
|
|
int low_i,high_i,low_j,high_j;
|
|
|
|
int viewer_i,viewer_j;
|
|
|
|
org_i = org_2dy;
|
|
|
|
org_j = org_2dx;
|
|
|
|
|
|
|
|
low_i = 0; high_i = grid_w-1;
|
|
|
|
low_j = 0; high_j = grid_h-1;
|
|
|
|
|
|
|
|
//@@start_point.x = org_point->x - GRID_SCALE*(org_i - low_i);
|
|
|
|
//@@start_point.z = org_point->z - GRID_SCALE*(org_j - low_j);
|
|
|
|
//@@start_point.y = org_point->y;
|
2014-09-28 21:09:27 +00:00
|
|
|
terrain_y_cache get_dy_vec;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if !DXX_USE_OGL
|
2015-11-06 03:51:10 +00:00
|
|
|
Interpolation_method = 1;
|
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-11-02 03:43:47 +00:00
|
|
|
{
|
|
|
|
const auto tv = vm_vec_copy_scale(surface_orient.rvec,GRID_SCALE);
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_rotate_delta_vec(delta_i,tv);
|
2014-11-02 03:43:47 +00:00
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto tv = vm_vec_copy_scale(surface_orient.fvec,GRID_SCALE);
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_rotate_delta_vec(delta_j,tv);
|
2014-11-02 03:43:47 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-11-02 03:43:57 +00:00
|
|
|
auto start_point = vm_vec_scale_add(org_point,surface_orient.rvec,-(org_i - low_i)*GRID_SCALE);
|
2014-09-28 21:43:14 +00:00
|
|
|
vm_vec_scale_add2(start_point,surface_orient.fvec,-(org_j - low_j)*GRID_SCALE);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-10-29 03:24:31 +00:00
|
|
|
{
|
|
|
|
const auto tv = vm_vec_sub(Viewer->pos,start_point);
|
2014-09-28 21:11:48 +00:00
|
|
|
viewer_i = vm_vec_dot(tv,surface_orient.rvec) / GRID_SCALE;
|
|
|
|
viewer_j = vm_vec_dot(tv,surface_orient.fvec) / GRID_SCALE;
|
2014-10-29 03:24:31 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-11-13 03:41:29 +00:00
|
|
|
auto last_p = g3_rotate_point(start_point);
|
2006-03-20 17:12:09 +00:00
|
|
|
save_p_low = last_p;
|
|
|
|
|
2014-07-04 04:17:37 +00:00
|
|
|
g3s_point save_row[GRID_MAX_SIZE]{};
|
|
|
|
// Is this needed?
|
2006-03-20 17:12:09 +00:00
|
|
|
for (j=low_j;j<=high_j;j++) {
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(save_row[j],last_p,get_dy_vec(HEIGHT(low_i,j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
if (j==high_j)
|
|
|
|
save_p_high = last_p;
|
|
|
|
else
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(last_p,last_p,delta_j);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2014-09-28 21:09:27 +00:00
|
|
|
int mine_tiles_drawn = 0; //flags to tell if all 4 tiles under mine have drawn
|
2006-03-20 17:12:09 +00:00
|
|
|
for (i=low_i;i<viewer_i;i++) {
|
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(save_p_low,save_p_low,delta_i);
|
2006-03-20 17:12:09 +00:00
|
|
|
last_p = save_p_low;
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(last_p2,last_p,get_dy_vec(HEIGHT(i+1,low_j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
for (j=low_j;j<viewer_j;j++) {
|
|
|
|
g3s_point p2;
|
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(p,last_p,delta_j);
|
|
|
|
g3_add_delta_vec(p2,p,get_dy_vec(HEIGHT(i+1,j+1)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
draw_cell(canvas, i, j, save_row[j], save_row[j+1], p2, last_p2, mine_tiles_drawn);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
last_p = p;
|
|
|
|
save_row[j] = last_p2;
|
|
|
|
last_p2 = p2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-09-28 21:09:37 +00:00
|
|
|
vm_vec_negate(delta_j); //don't have a delta sub...
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(save_p_high,save_p_high,delta_i);
|
2006-03-20 17:12:09 +00:00
|
|
|
last_p = save_p_high;
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(last_p2,last_p,get_dy_vec(HEIGHT(i+1,high_j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
for (j=high_j-1;j>=viewer_j;j--) {
|
|
|
|
g3s_point p2;
|
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(p,last_p,delta_j);
|
|
|
|
g3_add_delta_vec(p2,p,get_dy_vec(HEIGHT(i+1,j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
draw_cell(canvas, i, j, save_row[j], save_row[j+1], last_p2, p2, mine_tiles_drawn);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
last_p = p;
|
|
|
|
save_row[j+1] = last_p2;
|
|
|
|
last_p2 = p2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
save_row[j+1] = last_p2;
|
|
|
|
|
2014-09-28 21:09:37 +00:00
|
|
|
vm_vec_negate(delta_j); //restore sign of j
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//now do i from other end
|
|
|
|
|
2014-09-28 21:09:37 +00:00
|
|
|
vm_vec_negate(delta_i); //going the other way now...
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
//@@start_point.x += (high_i-low_i)*GRID_SCALE;
|
2014-09-28 21:43:14 +00:00
|
|
|
vm_vec_scale_add2(start_point,surface_orient.rvec,(high_i-low_i)*GRID_SCALE);
|
2014-10-02 03:02:35 +00:00
|
|
|
g3_rotate_point(last_p,start_point);
|
2006-03-20 17:12:09 +00:00
|
|
|
save_p_low = last_p;
|
|
|
|
|
|
|
|
for (j=low_j;j<=high_j;j++) {
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(save_row[j],last_p,get_dy_vec(HEIGHT(high_i,j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
if (j==high_j)
|
|
|
|
save_p_high = last_p;
|
|
|
|
else
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(last_p,last_p,delta_j);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i=high_i-1;i>=viewer_i;i--) {
|
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(save_p_low,save_p_low,delta_i);
|
2006-03-20 17:12:09 +00:00
|
|
|
last_p = save_p_low;
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(last_p2,last_p,get_dy_vec(HEIGHT(i,low_j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
for (j=low_j;j<viewer_j;j++) {
|
|
|
|
g3s_point p2;
|
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(p,last_p,delta_j);
|
|
|
|
g3_add_delta_vec(p2,p,get_dy_vec(HEIGHT(i,j+1)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
draw_cell(canvas, i, j, last_p2, p2, save_row[j+1], save_row[j], mine_tiles_drawn);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
last_p = p;
|
|
|
|
save_row[j] = last_p2;
|
|
|
|
last_p2 = p2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-09-28 21:09:37 +00:00
|
|
|
vm_vec_negate(delta_j); //don't have a delta sub...
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(save_p_high,save_p_high,delta_i);
|
2006-03-20 17:12:09 +00:00
|
|
|
last_p = save_p_high;
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(last_p2,last_p,get_dy_vec(HEIGHT(i,high_j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
for (j=high_j-1;j>=viewer_j;j--) {
|
|
|
|
g3s_point p2;
|
|
|
|
|
2014-10-02 03:02:36 +00:00
|
|
|
g3_add_delta_vec(p,last_p,delta_j);
|
|
|
|
g3_add_delta_vec(p2,p,get_dy_vec(HEIGHT(i,j)));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-03-11 19:56:26 +00:00
|
|
|
draw_cell(canvas, i, j, p2, last_p2, save_row[j+1], save_row[j], mine_tiles_drawn);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
last_p = p;
|
|
|
|
save_row[j+1] = last_p2;
|
|
|
|
last_p2 = p2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
save_row[j+1] = last_p2;
|
|
|
|
|
2014-09-28 21:09:37 +00:00
|
|
|
vm_vec_negate(delta_j); //restore sign of j
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_height_array()
|
|
|
|
{
|
2015-01-23 03:55:04 +00:00
|
|
|
height_array.reset();
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2012-11-11 22:12:51 +00:00
|
|
|
void load_terrain(const char *filename)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
grs_bitmap height_bitmap;
|
|
|
|
int iff_error;
|
|
|
|
int i,j;
|
|
|
|
ubyte h,min_h,max_h;
|
|
|
|
|
2016-05-28 17:31:27 +00:00
|
|
|
iff_error = iff_read_bitmap(filename, height_bitmap, NULL);
|
2006-03-20 17:12:09 +00:00
|
|
|
if (iff_error != IFF_NO_ERROR) {
|
|
|
|
Error("File %s - IFF error: %s",filename,iff_errormsg(iff_error));
|
|
|
|
}
|
|
|
|
grid_w = height_bitmap.bm_w;
|
|
|
|
grid_h = height_bitmap.bm_h;
|
|
|
|
|
|
|
|
Assert(grid_w <= GRID_MAX_SIZE);
|
|
|
|
Assert(grid_h <= GRID_MAX_SIZE);
|
|
|
|
|
2015-01-23 03:55:04 +00:00
|
|
|
height_array.reset(height_bitmap.get_bitmap_data());
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
max_h=0; min_h=255;
|
|
|
|
for (i=0;i<grid_w;i++)
|
|
|
|
for (j=0;j<grid_h;j++) {
|
|
|
|
|
|
|
|
h = HEIGHT(i,j);
|
|
|
|
|
|
|
|
if (h > max_h)
|
|
|
|
max_h = h;
|
|
|
|
|
|
|
|
if (h < min_h)
|
|
|
|
min_h = h;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0;i<grid_w;i++)
|
|
|
|
for (j=0;j<grid_h;j++)
|
|
|
|
HEIGHT(i,j) -= min_h;
|
|
|
|
|
|
|
|
|
|
|
|
// d_free(height_bitmap.bm_data);
|
|
|
|
|
|
|
|
terrain_bm = terrain_bitmap;
|
|
|
|
|
|
|
|
build_light_table();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-02 03:43:29 +00:00
|
|
|
static void get_pnt(vms_vector &p,int i,int j)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2009-11-30 22:42:55 +00:00
|
|
|
// added on 02/20/99 by adb to prevent overflow
|
|
|
|
if (i >= grid_h) i = grid_h - 1;
|
|
|
|
if (i == grid_h - 1 && j >= grid_w) j = grid_w - 1;
|
|
|
|
// end additions by adb
|
2014-11-02 03:43:29 +00:00
|
|
|
p.x = GRID_SCALE*i;
|
|
|
|
p.z = GRID_SCALE*j;
|
|
|
|
p.y = HEIGHT(i,j)*HEIGHT_SCALE;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2016-07-16 16:52:04 +00:00
|
|
|
constexpr vms_vector light{0x2e14,0xe8f5,0x5eb8};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2014-11-02 03:43:29 +00:00
|
|
|
static fix get_face_light(const vms_vector &p0,const vms_vector &p1,const vms_vector &p2)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2014-11-02 03:43:29 +00:00
|
|
|
const auto norm = vm_vec_normal(p0,p1,p2);
|
2014-09-28 21:11:48 +00:00
|
|
|
return -vm_vec_dot(norm,light);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2013-10-27 22:00:14 +00:00
|
|
|
static fix get_avg_light(int i,int j)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
vms_vector pp,p[6];
|
|
|
|
fix sum;
|
|
|
|
int f;
|
|
|
|
|
2014-11-02 03:43:29 +00:00
|
|
|
get_pnt(pp,i,j);
|
|
|
|
get_pnt(p[0],i-1,j);
|
|
|
|
get_pnt(p[1],i,j-1);
|
|
|
|
get_pnt(p[2],i+1,j-1);
|
|
|
|
get_pnt(p[3],i+1,j);
|
|
|
|
get_pnt(p[4],i,j+1);
|
|
|
|
get_pnt(p[5],i-1,j+1);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
for (f=0,sum=0;f<6;f++)
|
2014-11-02 03:43:29 +00:00
|
|
|
sum += get_face_light(pp,p[f],p[(f+1)%5]);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
return sum/6;
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_light_table()
|
|
|
|
{
|
2014-07-22 03:11:56 +00:00
|
|
|
light_array.reset();
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2013-09-22 22:26:27 +00:00
|
|
|
static void build_light_table()
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2014-07-22 03:11:56 +00:00
|
|
|
std::size_t alloc = grid_w*grid_h;
|
2014-08-16 04:15:16 +00:00
|
|
|
light_array = make_unique<uint8_t[]>(alloc);
|
2014-07-22 03:11:56 +00:00
|
|
|
memset(light_array.get(), 0, alloc);
|
2006-03-20 17:12:09 +00:00
|
|
|
int i,j;
|
2017-02-22 03:05:43 +00:00
|
|
|
fix l, l2, min_l = INT32_MAX, max_l = 0;
|
2006-03-20 17:12:09 +00:00
|
|
|
for (i=1;i<grid_w;i++)
|
|
|
|
for (j=1;j<grid_h;j++) {
|
|
|
|
l = get_avg_light(i,j);
|
|
|
|
|
|
|
|
if (l > max_l)
|
|
|
|
max_l = l;
|
|
|
|
|
|
|
|
if (l < min_l)
|
|
|
|
min_l = l;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=1;i<grid_w;i++)
|
|
|
|
for (j=1;j<grid_h;j++) {
|
|
|
|
|
|
|
|
l = get_avg_light(i,j);
|
|
|
|
|
|
|
|
if (min_l == max_l) {
|
|
|
|
LIGHT(i,j) = l>>8;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
l2 = fixdiv((l-min_l),(max_l-min_l));
|
|
|
|
|
|
|
|
if (l2==f1_0)
|
|
|
|
l2--;
|
|
|
|
|
|
|
|
LIGHT(i,j) = l2>>8;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|