diff --git a/common/3d/draw.cpp b/common/3d/draw.cpp index cd280b63b..76aedf860 100644 --- a/common/3d/draw.cpp +++ b/common/3d/draw.cpp @@ -205,7 +205,7 @@ static void must_clip_tmap_face(int nv,g3s_codes cc,grs_bitmap *bm); //draw a texture-mapped face. //returns 1 if off screen, 0 if drew -void g3_draw_tmap(int nv,g3s_point **pointlist,const g3s_uvl *uvl_list,g3s_lrgb *light_rgb,grs_bitmap *bm) +void _g3_draw_tmap(unsigned nv,g3s_point **pointlist,const g3s_uvl *uvl_list,const g3s_lrgb *light_rgb,grs_bitmap *bm) { int i; g3s_point **bufptr; diff --git a/common/3d/rod.cpp b/common/3d/rod.cpp index 8b0ba937e..a30e5f779 100644 --- a/common/3d/rod.cpp +++ b/common/3d/rod.cpp @@ -104,21 +104,21 @@ void g3_draw_rod_tmap(grs_bitmap *bitmap,g3s_point *bot_point,fix bot_width,g3s_ if (calc_rod_corners(rod,bot_point,bot_width,top_point,top_width)) return; - g3s_uvl uvl_list[4] = { - { 0x0200,0x0200,0 }, - { 0xfe00,0x0200,0 }, - { 0xfe00,0xfe00,0 }, - { 0x0200,0xfe00,0 } - }; - uvl_list[0].l = uvl_list[1].l = uvl_list[2].l = uvl_list[3].l = static_cast(light.r+light.g+light.b)/3; - g3s_lrgb lrgb_list[4] = { + const fix average_light = static_cast(light.r+light.g+light.b)/3; + const array uvl_list{{ + { 0x0200, 0x0200, average_light }, + { 0xfe00, 0x0200, average_light }, + { 0xfe00, 0xfe00, average_light }, + { 0x0200, 0xfe00, average_light } + }}; + const array lrgb_list{{ light, light, light, light, - }; + }}; - g3_draw_tmap(4,rod.point_list,uvl_list,lrgb_list,bitmap); + g3_draw_tmap(rod.point_list,uvl_list,lrgb_list,bitmap); } #ifndef OGL diff --git a/common/include/3d.h b/common/include/3d.h index 3580940ba..bedcc6c6a 100644 --- a/common/include/3d.h +++ b/common/include/3d.h @@ -179,9 +179,28 @@ ubyte g3_add_delta_vec(g3s_point *dest,const g3s_point *src,const vms_vector *de //returns 1 if off screen, 0 if drew bool g3_draw_poly(int nv,g3s_point **pointlist); +static const std::size_t MAX_POINTS_PER_POLY = 25; + //draw a texture-mapped face. //returns 1 if off screen, 0 if drew -void g3_draw_tmap(int nv,g3s_point **pointlist,const g3s_uvl *uvl_list,g3s_lrgb *light_rgb,grs_bitmap *bm); +void _g3_draw_tmap(unsigned nv, g3s_point **pointlist, const g3s_uvl *uvl_list, const g3s_lrgb *light_rgb, grs_bitmap *bm); + +template +static inline void g3_draw_tmap(unsigned nv, g3s_point **pointlist, const array &uvl_list, const array &light_rgb, grs_bitmap *bm) +{ + static_assert(N <= MAX_POINTS_PER_POLY, "too many points in tmap"); +#ifdef DXX_HAVE_BUILTIN_CONSTANT_P + if (__builtin_constant_p(nv > N) && nv > N) + DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_tmap_overread, "reading beyond array"); +#endif + _g3_draw_tmap(nv, pointlist, &uvl_list[0], &light_rgb[0], bm); +} + +template +static inline void g3_draw_tmap(g3s_point **pointlist, const array &uvl_list, const array &light_rgb, grs_bitmap *bm) +{ + g3_draw_tmap(N, pointlist, uvl_list, light_rgb, bm); +} //draw a sortof sphere - i.e., the 2d radius is proportional to the 3d //radius, but not to the distance from the eye @@ -211,12 +230,19 @@ static inline void g3_check_and_draw_poly(int nv, g3s_point **pointlist) g3_draw_poly(nv,pointlist); } -static inline void g3_check_and_draw_tmap(int nv, g3s_point **pointlist, const g3s_uvl *uvl_list, g3s_lrgb *light_rgb, grs_bitmap *bm) +template +static inline void g3_check_and_draw_tmap(unsigned nv, g3s_point **pointlist, const array &uvl_list, const array &light_rgb, grs_bitmap *bm) { if (do_facing_check(pointlist)) g3_draw_tmap(nv,pointlist,uvl_list,light_rgb,bm); } +template +static inline void g3_check_and_draw_tmap(g3s_point **pointlist, const array &uvl_list, const array &light_rgb, grs_bitmap *bm) +{ + g3_check_and_draw_tmap(N, pointlist, uvl_list, light_rgb, bm); +} + //draws a line. takes two points. bool g3_draw_line(g3s_point *p0,g3s_point *p1); diff --git a/common/include/ogl_init.h b/common/include/ogl_init.h index 66257ab30..ab4e5460c 100644 --- a/common/include/ogl_init.h +++ b/common/include/ogl_init.h @@ -107,7 +107,18 @@ unsigned char ogl_ugpixel( grs_bitmap * bitmap, int x, int y ); void ogl_ulinec(int left, int top, int right, int bot, int c); #include "3d.h" -void g3_draw_tmap_2(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,g3s_lrgb *light_rgb, grs_bitmap *bmbot,grs_bitmap *bm, int orient); +void _g3_draw_tmap_2(unsigned nv, g3s_point **pointlist, const g3s_uvl *uvl_list, const g3s_lrgb *light_rgb, grs_bitmap *bmbot, grs_bitmap *bm, int orient); + +template +static inline void g3_draw_tmap_2(unsigned nv, g3s_point **pointlist, const array &uvl_list, const array &light_rgb, grs_bitmap *bmbot, grs_bitmap *bm, int orient) +{ + static_assert(N <= MAX_POINTS_PER_POLY, "too many points in tmap"); +#ifdef DXX_HAVE_BUILTIN_CONSTANT_P + if (__builtin_constant_p(nv) && nv > N) + DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_tmap_overread, "reading beyond array"); +#endif + _g3_draw_tmap_2(nv, pointlist, &uvl_list[0], &light_rgb[0], bmbot, bm, orient); +} void ogl_draw_vertex_reticle(int cross,int primary,int secondary,int color,int alpha,int size_offs); void ogl_toggle_depth_test(int enable); diff --git a/similar/3d/interp.cpp b/similar/3d/interp.cpp index 92ab390f1..8dd31b738 100644 --- a/similar/3d/interp.cpp +++ b/similar/3d/interp.cpp @@ -30,8 +30,6 @@ static const unsigned OP_SUBCALL = 6; //call a subobject static const unsigned OP_DEFP_START = 7; //defpoints with start static const unsigned OP_GLOW = 8; //glow value for next poly -#define MAX_POINTS_PER_POLY 25 - short highest_texture_num; int g3d_interp_outline; @@ -373,7 +371,6 @@ void g3_draw_polygon_model(ubyte *p,grs_bitmap **model_bitmaps,vms_angvec *anim_ case OP_TMAPPOLY: { int nv = w(p+2); - g3s_uvl *uvl_list; Assert( nv < MAX_POINTS_PER_POLY ); if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) { @@ -398,12 +395,12 @@ void g3_draw_polygon_model(ubyte *p,grs_bitmap **model_bitmaps,vms_angvec *anim_ } //now poke light into l values - uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2); - + array uvl_list; array lrgb_list; for (i=0;i uvl_copy; + array dyn_light; int i; g3s_point *pointlist[8]; @@ -368,15 +368,11 @@ static void check_face(segnum_t segnum, int sidenum, int facenum, int nv, int *v if (_search_mode) { int save_lighting; + array uvl_copy; + array dyn_light{}; + array pointlist; #ifndef OGL grs_bitmap *bm; -#endif - g3s_uvl uvl_copy[8]; - g3s_lrgb dyn_light[8]; - g3s_point *pointlist[4]; - - memset(dyn_light, 0, sizeof(dyn_light)); -#ifndef OGL if (tmap2 > 0 ) bm = texmerge_get_cached_bitmap( tmap1, tmap2 ); else diff --git a/similar/main/terrain.cpp b/similar/main/terrain.cpp index 6b4dfec9c..956410198 100644 --- a/similar/main/terrain.cpp +++ b/similar/main/terrain.cpp @@ -83,8 +83,8 @@ static void draw_cell(int i,int j,g3s_point *p0,g3s_point *p1,g3s_point *p2,g3s_ pointlist[0] = p0; pointlist[1] = p1; pointlist[2] = p3; - g3s_lrgb lrgb_list1[3]; - g3s_uvl uvl_list1[3]; + array lrgb_list1; + array uvl_list1; 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); @@ -93,7 +93,7 @@ static void draw_cell(int i,int j,g3s_point *p0,g3s_point *p1,g3s_point *p2,g3s_ 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; - g3_check_and_draw_tmap(3,pointlist,uvl_list1,lrgb_list1,terrain_bm); + g3_check_and_draw_tmap(pointlist,uvl_list1,lrgb_list1,terrain_bm); if (terrain_outline) { int lsave=Lighting_on; Lighting_on=0; @@ -105,8 +105,8 @@ static void draw_cell(int i,int j,g3s_point *p0,g3s_point *p1,g3s_point *p2,g3s_ pointlist[0] = p1; pointlist[1] = p2; - g3s_uvl uvl_list2[3]; - g3s_lrgb lrgb_list2[3]; + array uvl_list2; + array lrgb_list2; 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); @@ -115,7 +115,7 @@ static void draw_cell(int i,int j,g3s_point *p0,g3s_point *p1,g3s_point *p2,g3s_ 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; - g3_check_and_draw_tmap(3,pointlist,uvl_list2,lrgb_list2,terrain_bm); + g3_check_and_draw_tmap(pointlist,uvl_list2,lrgb_list2,terrain_bm); if (terrain_outline) { int lsave=Lighting_on; Lighting_on=0;