- Cleanup of the voxel code.

* moving polymost_voxdraw into polymost.cpp.
* consolidated all remaining voxel code in hw_voxels.cpp. All original Build voxel code is completely gone now, except for polymost_voxdraw, so this got moved out of the build/ folder.
* integrate Blood's voxel init code into the main function.
* some further cleanup was allowed as a result of this, so engineInit is gone now because these parts can now be done outside the games' app_init functions.
This commit is contained in:
Christoph Oelckers 2021-04-05 13:55:36 +02:00
parent ba90f444dd
commit e30dc82676
29 changed files with 362 additions and 486 deletions

View file

@ -1033,7 +1033,6 @@ set (PCH_SOURCES
build/src/engine.cpp
build/src/mdsprite.cpp
build/src/polymost.cpp
build/src/voxmodel.cpp
core/movie/playmve.cpp
core/automap.cpp
@ -1081,6 +1080,7 @@ set (PCH_SOURCES
core/rendering/hw_entrypoint.cpp
core/rendering/hw_models.cpp
core/rendering/hw_voxels.cpp
core/rendering/scene/hw_clipper.cpp
core/rendering/scene/hw_walls.cpp
core/rendering/scene/hw_flats.cpp

View file

@ -198,7 +198,7 @@ enum {
PALETTE_TRANSLUC = 1<<2,
};
EXTERN int32_t g_visibility, parallaxvisibility;
EXTERN int32_t g_visibility;
// blendtable[1] to blendtable[numalphatabs] are considered to be
// alpha-blending tables:
@ -267,12 +267,6 @@ extern FixedBitArray<MAXSECTORS> gotsector;
extern uint32_t drawlinepat;
extern int32_t novoxmips;
extern int16_t tiletovox[MAXTILES];
extern int32_t voxscale[MAXVOXELS];
extern char g_haveVoxels;
extern uint8_t globalr, globalg, globalb;
enum {
@ -360,10 +354,6 @@ void engineLoadBoard(const char *filename, int flags, vec3_t *dapos, int16_t *da
void loadMapBackup(const char* filename);
void G_LoadMapHack(const char* filename, const unsigned char*);
int32_t qloadkvx(int32_t voxindex, const char *filename);
void vox_undefine(int32_t const);
void vox_deinit();
void videoSetCorrectedAspect();
void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
void renderSetAspect(int32_t daxrange, int32_t daaspect);
@ -596,7 +586,6 @@ int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, f
EXTERN int32_t nextvoxid;
EXTERN int8_t voxreserve[(MAXVOXELS+7)>>3];
EXTERN int8_t voxrotate[(MAXVOXELS+7)>>3];
#ifdef USE_OPENGL
// TODO: dynamically allocate this
@ -626,13 +615,7 @@ inline int32_t md_tilehasmodel(int32_t const tilenume, int32_t const pal)
}
#endif // defined USE_OPENGL
inline int tilehasmodelorvoxel(int const tilenume, int pal)
{
UNREFERENCED_PARAMETER(pal);
return
(mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) ||
(r_voxels && tiletovox[tilenume] != -1);
}
int tilehasmodelorvoxel(int const tilenume, int pal);
int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume,
int32_t skinnum, float smoothduration, int32_t pal);
@ -733,9 +716,6 @@ extern int32_t(*insertsprite_replace)(int16_t sectnum, int16_t statnum);
extern int32_t(*deletesprite_replace)(int16_t spritenum);
extern int32_t(*changespritesect_replace)(int16_t spritenum, int16_t newsectnum);
extern int32_t(*changespritestat_replace)(int16_t spritenum, int16_t newstatnum);
#ifdef USE_OPENGL
extern void(*PolymostProcessVoxels_Callback)(void);
#endif
// Masking these into the object index to keep it in 16 bit was probably the single most dumbest and pointless thing Build ever did.
// Gonna be fun to globally replace these to finally lift the limit this imposes on map size.

View file

@ -177,25 +177,6 @@ struct md3model_t : public idmodel_t
*/
};
#define VOXBORDWIDTH 1 //use 0 to save memory, but has texture artifacts; 1 looks better...
#define VOXUSECHAR 0
#if (VOXUSECHAR != 0)
typedef struct { uint8_t x, y, z, u, v; } vert_t;
#else
typedef struct { uint16_t x, y, z, u, v; } vert_t;
#endif
typedef struct { vert_t v[4]; } voxrect_t;
struct voxmodel_t : public mdmodel_t
{
FVoxelModel* model = nullptr;
vec3_t siz;
vec3f_t piv;
int32_t is8bit;
};
EXTERN mdmodel_t **models;
FGameTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact);
@ -206,11 +187,6 @@ EXTERN void md3_vox_calcmat_common(tspriteptr_t tspr, const vec3f_t *a0, float f
EXTERN int32_t mdpause;
EXTERN int32_t nextmodelid;
EXTERN voxmodel_t *voxmodels[MAXVOXELS];
void voxfree(voxmodel_t *m);
voxmodel_t *voxload(int lumpnum);
int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr, bool rotate);
#endif // defined USE_OPENGL

View file

@ -32,7 +32,6 @@ void polymost_deletesprite(int num);
int32_t polymost_maskWallHasTranslucency(walltype const * const wall);
int32_t polymost_spriteHasTranslucency(spritetype const * const tspr);
int32_t polymost_spriteIsModelOrVoxel(spritetype const * const tspr);
void polymost_glreset(void);
void polymost_scansector(int32_t sectnum);

View file

@ -17,6 +17,7 @@
#include "gamecontrol.h"
#include "palettecontainer.h"
#include "mapinfo.h"
#include "hw_voxels.h"
int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags);
int tileSetSkybox(int picnum, int palnum, const char** facenames, int flags);
@ -1117,7 +1118,7 @@ static int32_t defsparser(scriptfile *script)
break;
}
if (qloadkvx(nextvoxid, fn))
if (voxDefine(nextvoxid, fn))
{
Printf("Failure loading voxel file \"%s\"\n",fn.GetChars());
break;
@ -1588,7 +1589,7 @@ static int32_t defsparser(scriptfile *script)
break;
}
if (qloadkvx(nextvoxid, fn))
if (voxDefine(nextvoxid, fn))
{
voxelpos.Message(MSG_ERROR, "Failure loading voxel file \"%s\"",fn.GetChars());
break;
@ -1629,14 +1630,14 @@ static int32_t defsparser(scriptfile *script)
{
double scale=1.0;
scriptfile_getdouble(script,&scale);
voxscale[lastvoxid] = (int32_t)(65536*scale);
voxscale[lastvoxid] = (float)scale;
if (voxmodels[lastvoxid])
voxmodels[lastvoxid]->scale = scale;
break;
}
case T_ROTATE:
voxrotate[lastvoxid>>3] |= (1 << (lastvoxid&7));
voxrotate.Set(lastvoxid);
break;
}
}

View file

@ -32,6 +32,7 @@
#include "gamecontrol.h"
#include "render.h"
#include "gamefuncs.h"
#include "hw_voxels.h"
#ifdef USE_OPENGL
# include "mdsprite.h"
@ -53,18 +54,6 @@ uint8_t globalr = 255, globalg = 255, globalb = 255;
int16_t pskybits_override = -1;
// This was on the cache but is permanently allocated, so put it into something static. This needs some rethinking anyway
static TArray<TArray<uint8_t>> voxelmemory;
int16_t tiletovox[MAXTILES];
int voxlumps[MAXVOXELS];
char g_haveVoxels;
//#define kloadvoxel loadvoxel
int32_t novoxmips = 1;
int32_t voxscale[MAXVOXELS];
static int32_t beforedrawrooms = 1;
int32_t globalflags;
@ -151,7 +140,6 @@ fixed_t qglobalang;
int32_t globalpal, globalfloorpal, cosglobalang, singlobalang;
int32_t cosviewingrangeglobalang, sinviewingrangeglobalang;
int32_t xyaspect;
int32_t viewingrangerecip;
static int32_t globalxpanning, globalypanning;
@ -671,26 +659,8 @@ int32_t enginePreInit(void)
//
int32_t engineInit(void)
{
if (engineLoadTables())
return 1;
xyaspect = -1;
voxelmemory.Reset();
for (int i=0; i<MAXTILES; i++)
tiletovox[i] = -1;
for (auto& v : voxscale) v = 65536;
memset(voxrotate, 0, sizeof(voxrotate));
paletteloaded = 0;
engineLoadTables();
g_visibility = 512;
parallaxvisibility = 512;
GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes.
gi->loadPalette();
if (!mdinited) mdinit();
return 0;
}
@ -750,80 +720,6 @@ void initspritelists(void)
Numsprites = 0;
}
//
// qloadkvx
//
int32_t qloadkvx(int32_t voxindex, const char *filename)
{
if ((unsigned)voxindex >= MAXVOXELS)
return -1;
auto fil = fileSystem.OpenFileReader(filename);
if (!fil.isOpen())
return -1;
int32_t lengcnt = 0;
const int32_t lengtot = fil.GetLength();
for (bssize_t i=0; i<MAXVOXMIPS; i++)
{
int32_t dasiz = fil.ReadInt32();
voxelmemory.Reserve(1);
voxelmemory.Last() = fil.Read(dasiz);
lengcnt += dasiz+4;
if (lengcnt >= lengtot-768)
break;
}
if (voxmodels[voxindex])
{
voxfree(voxmodels[voxindex]);
voxmodels[voxindex] = NULL;
}
voxlumps[voxindex] = fileSystem.FindFile(filename);
g_haveVoxels = 1;
return 0;
}
void vox_undefine(int32_t const tile)
{
int voxindex = tiletovox[tile];
if (voxindex < 0)
return;
if (voxmodels[voxindex])
{
voxfree(voxmodels[voxindex]);
voxmodels[voxindex] = NULL;
}
voxscale[voxindex] = 65536;
voxrotate[voxindex>>3] &= ~(1 << (voxindex&7));
tiletovox[tile] = -1;
// TODO: nextvoxid
}
void vox_deinit()
{
for (auto &vox : voxmodels)
{
voxfree(vox);
vox = nullptr;
}
}
//
// inside
//
@ -1865,3 +1761,10 @@ void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z)
}
int tilehasmodelorvoxel(int const tilenume, int pal)
{
UNREFERENCED_PARAMETER(pal);
return
(mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) ||
(r_voxels && tiletovox[tilenume] != -1);
}

View file

@ -16,6 +16,7 @@
#include "texturemanager.h"
#include "hw_renderstate.h"
#include "printf.h"
#include "hw_voxels.h"
#include "../../glbackend/glbackend.h"
static int32_t curextra=MAXTILES;
@ -23,6 +24,7 @@ static int32_t curextra=MAXTILES;
#define MIN_CACHETIME_PRINT 10
using namespace Polymost;
int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate);
static int32_t addtileP(int32_t model,int32_t tile,int32_t pallet)
{
@ -1538,6 +1540,11 @@ int32_t polymost_mddraw(tspriteptr_t tspr)
return 0;
}
void voxfree(voxmodel_t* m)
{
if (m) delete m;
}
static void mdfree(mdmodel_t *vm)
{
if (vm->mdnum == 1) { voxfree((voxmodel_t *)vm); return; }

View file

@ -26,6 +26,7 @@ Ken Silverman's official web site: http://www.advsys.net/ken
#include "hw_drawinfo.h"
#include "gamestruct.h"
#include "gamestruct.h"
#include "hw_voxels.h"
typedef struct {
@ -35,11 +36,13 @@ typedef struct {
} vec3d_t;
static_assert(sizeof(vec3d_t) == sizeof(double) * 3);
int32_t xyaspect = -1;
int skiptile = -1;
FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap, int remap = 0);
int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate);
int checkTranslucentReplacement(FTextureID picnum, int pal);
@ -2750,14 +2753,14 @@ void polymost_drawsprite(int32_t snum)
if ((tspr->cstat & 48) != 48 && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]])
{
int num = tiletovox[tspr->picnum];
if (polymost_voxdraw(voxmodels[num], tspr, voxrotate[num>>3] & (1<<(num&7)))) return;
if (polymost_voxdraw(voxmodels[num], tspr, voxrotate[num])) return;
break; // else, render as flat sprite
}
if ((tspr->cstat & 48) == 48 && tspr->picnum < MAXVOXELS && voxmodels[tspr->picnum])
{
int num = tspr->picnum;
polymost_voxdraw(voxmodels[tspr->picnum], tspr, voxrotate[num >> 3] & (1 << (num & 7)));
polymost_voxdraw(voxmodels[tspr->picnum], tspr, voxrotate[num]);
return;
}
}
@ -3494,6 +3497,23 @@ static void sortsprites(int const start, int const end)
}
}
static bool spriteIsModelOrVoxel(const spritetype* tspr)
{
if ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].flags & SPREXT_NOTMD)
return false;
if (hw_models)
{
auto& mdinfo = tile2model[Ptile2tile(tspr->picnum, tspr->pal)];
if (mdinfo.modelid >= 0 && mdinfo.framenum >= 0) return true;
}
auto slabalign = (tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB;
if (r_voxels && !slabalign && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) return true;
return (slabalign && voxmodels[tspr->picnum]);
}
//
// drawmasks
//
@ -3817,4 +3837,151 @@ void renderSetAspect(int32_t daxrange, int32_t daaspect)
xdimscale = Scale(320, xyaspect, xdimen);
}
//Draw voxel model as perfect cubes
int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate)
{
float f, g, k0, zoff;
if ((intptr_t)m == (intptr_t)(-1)) // hackhackhack
return 0;
if ((tspr->cstat & 48) == 32)
return 0;
if ((tspr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate)
{
int myclock = (PlayClock << 3) + MulScale(4 << 3, pm_smoothratio, 16);
tspr->ang = (tspr->ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common.
}
vec3f_t m0 = { m->scale, m->scale, m->scale };
vec3f_t a0 = { 0, 0, m->zadd * m->scale };
k0 = m->bscale / 64.f;
f = (float)tspr->xrepeat * (256.f / 320.f) * k0;
if ((sprite[tspr->owner].cstat & 48) == 16)
{
f *= 1.25f;
a0.y -= tspr->xoffset * bcosf(spriteext[tspr->owner].angoff, -20);
a0.x += tspr->xoffset * bsinf(spriteext[tspr->owner].angoff, -20);
}
if (globalorientation & 8) { m0.z = -m0.z; a0.z = -a0.z; } //y-flipping
if (globalorientation & 4) { m0.x = -m0.x; a0.x = -a0.x; a0.y = -a0.y; } //x-flipping
m0.x *= f; a0.x *= f; f = -f;
m0.y *= f; a0.y *= f;
f = (float)tspr->yrepeat * k0;
m0.z *= f; a0.z *= f;
k0 = (float)(tspr->z + spriteext[tspr->owner].position_offset.z);
f = ((globalorientation & 8) && (sprite[tspr->owner].cstat & 48) != 0) ? -4.f : 4.f;
k0 -= (tspr->yoffset * tspr->yrepeat) * f * m->bscale;
zoff = m->siz.z * .5f;
if (!(tspr->cstat & 128))
zoff += m->piv.z;
else if ((tspr->cstat & 48) != 48)
{
zoff += m->piv.z;
zoff -= m->siz.z * .5f;
}
if (globalorientation & 8) zoff = m->siz.z - zoff;
f = (65536.f * 512.f) / ((float)xdimen * viewingrange);
g = 32.f / ((float)xdimen * Polymost::gxyaspect);
int const shadowHack = !!(tspr->clipdist & TSPR_FLAGS_MDHACK);
m0.y *= f; a0.y = (((float)(tspr->x + spriteext[tspr->owner].position_offset.x - globalposx)) * (1.f / 1024.f) + a0.y) * f;
m0.x *= -f; a0.x = (((float)(tspr->y + spriteext[tspr->owner].position_offset.y - globalposy)) * -(1.f / 1024.f) + a0.x) * -f;
m0.z *= g; a0.z = (((float)(k0 - globalposz - shadowHack)) * -(1.f / 16384.f) + a0.z) * g;
float mat[16];
md3_vox_calcmat_common(tspr, &a0, f, mat);
//Mirrors
if (Polymost::grhalfxdown10x < 0)
{
mat[0] = -mat[0];
mat[4] = -mat[4];
mat[8] = -mat[8];
mat[12] = -mat[12];
}
if (shadowHack)
{
GLInterface.SetDepthFunc(DF_LEqual);
}
int winding = ((Polymost::grhalfxdown10x >= 0) ^ ((globalorientation & 8) != 0) ^ ((globalorientation & 4) != 0)) ? Winding_CW : Winding_CCW;
GLInterface.SetCull(Cull_Back, winding);
float pc[4];
pc[0] = pc[1] = pc[2] = 1.f;
if (!shadowHack)
{
pc[3] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f;
pc[3] *= 1.0f - spriteext[tspr->owner].alpha;
SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f)
GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false);
}
else pc[3] = 1.f;
GLInterface.SetShade(std::max(0, globalshade), numshades);
//------------
//transform to Build coords
float omat[16];
memcpy(omat, mat, sizeof(omat));
f = 1.f / 64.f;
g = m0.x * f; mat[0] *= g; mat[1] *= g; mat[2] *= g;
g = m0.y * f; mat[4] = omat[8] * g; mat[5] = omat[9] * g; mat[6] = omat[10] * g;
g = -m0.z * f; mat[8] = omat[4] * g; mat[9] = omat[5] * g; mat[10] = omat[6] * g;
//
mat[12] -= (m->piv.x * mat[0] + m->piv.y * mat[4] + zoff * mat[8]);
mat[13] -= (m->piv.x * mat[1] + m->piv.y * mat[5] + zoff * mat[9]);
mat[14] -= (m->piv.x * mat[2] + m->piv.y * mat[6] + zoff * mat[10]);
//
//Let OpenGL (and perhaps hardware :) handle the matrix rotation
mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f;
for (int i = 0; i < 15; i++) mat[i] *= 1024.f;
// Adjust to backend coordinate system being used by the vertex buffer.
for (int i = 4; i < 8; i++)
{
float f = mat[i];
mat[i] = -mat[i + 4];
mat[i + 4] = -f;
}
GLInterface.SetMatrix(Matrix_Model, mat);
int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal);
GLInterface.SetPalswap(globalpal);
GLInterface.SetFade(sector[tspr->sectnum].floorpal);
auto tex = TexMan.GetGameTexture(m->model->GetPaletteTexture());
GLInterface.SetTexture(tex, TRANSLATION(Translation_Remap + curbasepal, globalpal), CLAMP_NOFILTER_XY, true);
GLInterface.SetModel(m->model, 0, 0, 0);
GLInterface.Draw(DT_Triangles, 0, 0);
GLInterface.SetModel(nullptr, 0, 0, 0);
GLInterface.SetCull(Cull_None);
if (shadowHack)
{
GLInterface.SetDepthFunc(DF_Less);
}
GLInterface.SetIdentityMatrix(Matrix_Model);
return 1;
}

View file

@ -1,230 +0,0 @@
//--------------------------------------- VOX LIBRARY BEGINS ---------------------------------------
#ifdef USE_OPENGL
#include "compat.h"
#include "build.h"
#include "engine_priv.h"
#include "polymost.h"
#include "mdsprite.h"
#include "v_video.h"
#include "flatvertices.h"
#include "hw_renderstate.h"
#include "texturemanager.h"
#include "voxels.h"
#include "gamecontrol.h"
#include "hw_models.h"
#include "printf.h"
#include "palette.h"
#include "../../glbackend/glbackend.h"
using namespace Polymost;
void voxfree(voxmodel_t *m)
{
if (m) delete m;
}
voxmodel_t *voxload(int lumpnum)
{
FVoxel* voxel = R_LoadKVX(lumpnum);
if (voxel != nullptr)
{
voxmodel_t* vm = new voxmodel_t;
*vm = {};
auto pivot = voxel->Mips[0].Pivot;
vm->mdnum = 1; //VOXel model id
vm->scale = vm->bscale = 1.f;
vm->piv.x = float(pivot.X);
vm->piv.y = float(pivot.Y);
vm->piv.z = float(pivot.Z);
vm->siz.x = voxel->Mips[0].SizeX;
vm->siz.y = voxel->Mips[0].SizeY;
vm->siz.z = voxel->Mips[0].SizeZ;
vm->is8bit = true;
voxel->Mips[0].Pivot.Zero(); // Needs to be taken out of the voxel data because it gets baked into the vertex buffer which we cannot use here.
vm->model = new FVoxelModel(voxel, true);
return vm;
}
return nullptr;
}
//Draw voxel model as perfect cubes
int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate)
{
float f, g, k0, zoff;
if ((intptr_t)m == (intptr_t)(-1)) // hackhackhack
return 0;
if ((tspr->cstat & 48) == 32)
return 0;
if ((tspr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate)
{
int myclock = (PlayClock << 3) + MulScale(4 << 3, pm_smoothratio, 16);
tspr->ang = (tspr->ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common.
}
vec3f_t m0 = { m->scale, m->scale, m->scale };
vec3f_t a0 = { 0, 0, m->zadd*m->scale };
k0 = m->bscale / 64.f;
f = (float) tspr->xrepeat * (256.f/320.f) * k0;
if ((sprite[tspr->owner].cstat&48)==16)
{
f *= 1.25f;
a0.y -= tspr->xoffset * bcosf(spriteext[tspr->owner].angoff, -20);
a0.x += tspr->xoffset * bsinf(spriteext[tspr->owner].angoff, -20);
}
if (globalorientation&8) { m0.z = -m0.z; a0.z = -a0.z; } //y-flipping
if (globalorientation&4) { m0.x = -m0.x; a0.x = -a0.x; a0.y = -a0.y; } //x-flipping
m0.x *= f; a0.x *= f; f = -f;
m0.y *= f; a0.y *= f;
f = (float) tspr->yrepeat * k0;
m0.z *= f; a0.z *= f;
k0 = (float) (tspr->z+spriteext[tspr->owner].position_offset.z);
f = ((globalorientation&8) && (sprite[tspr->owner].cstat&48)!=0) ? -4.f : 4.f;
k0 -= (tspr->yoffset*tspr->yrepeat)*f*m->bscale;
zoff = m->siz.z*.5f;
if (!(tspr->cstat&128))
zoff += m->piv.z;
else if ((tspr->cstat&48) != 48)
{
zoff += m->piv.z;
zoff -= m->siz.z*.5f;
}
if (globalorientation&8) zoff = m->siz.z-zoff;
f = (65536.f*512.f) / ((float)xdimen*viewingrange);
g = 32.f / ((float)xdimen*gxyaspect);
int const shadowHack = !!(tspr->clipdist & TSPR_FLAGS_MDHACK);
m0.y *= f; a0.y = (((float)(tspr->x+spriteext[tspr->owner].position_offset.x-globalposx)) * (1.f/1024.f) + a0.y) * f;
m0.x *=-f; a0.x = (((float)(tspr->y+spriteext[tspr->owner].position_offset.y-globalposy)) * -(1.f/1024.f) + a0.x) * -f;
m0.z *= g; a0.z = (((float)(k0 -globalposz - shadowHack)) * -(1.f/16384.f) + a0.z) * g;
float mat[16];
md3_vox_calcmat_common(tspr, &a0, f, mat);
//Mirrors
if (grhalfxdown10x < 0)
{
mat[0] = -mat[0];
mat[4] = -mat[4];
mat[8] = -mat[8];
mat[12] = -mat[12];
}
if (shadowHack)
{
GLInterface.SetDepthFunc(DF_LEqual);
}
int winding = ((grhalfxdown10x >= 0) ^ ((globalorientation & 8) != 0) ^ ((globalorientation & 4) != 0)) ? Winding_CW : Winding_CCW;
GLInterface.SetCull(Cull_Back, winding);
float pc[4];
pc[0] = pc[1] = pc[2] = 1.f;
if (!shadowHack)
{
pc[3] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f;
pc[3] *= 1.0f - spriteext[tspr->owner].alpha;
SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f)
GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false);
}
else pc[3] = 1.f;
GLInterface.SetShade(std::max(0, globalshade), numshades);
//------------
//transform to Build coords
float omat[16];
memcpy(omat, mat, sizeof(omat));
f = 1.f/64.f;
g = m0.x*f; mat[0] *= g; mat[1] *= g; mat[2] *= g;
g = m0.y*f; mat[4] = omat[8]*g; mat[5] = omat[9]*g; mat[6] = omat[10]*g;
g =-m0.z*f; mat[8] = omat[4]*g; mat[9] = omat[5]*g; mat[10] = omat[6]*g;
//
mat[12] -= (m->piv.x*mat[0] + m->piv.y*mat[4] + zoff*mat[8]);
mat[13] -= (m->piv.x*mat[1] + m->piv.y*mat[5] + zoff*mat[9]);
mat[14] -= (m->piv.x*mat[2] + m->piv.y*mat[6] + zoff*mat[10]);
//
//Let OpenGL (and perhaps hardware :) handle the matrix rotation
mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f;
for (int i = 0; i < 15; i++) mat[i] *= 1024.f;
// Adjust to backend coordinate system being used by the vertex buffer.
for (int i = 4; i < 8; i++)
{
float f = mat[i];
mat[i] = -mat[i + 4];
mat[i + 4] = -f;
}
GLInterface.SetMatrix(Matrix_Model, mat);
int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal);
GLInterface.SetPalswap(globalpal);
GLInterface.SetFade(sector[tspr->sectnum].floorpal);
auto tex = TexMan.GetGameTexture(m->model->GetPaletteTexture());
GLInterface.SetTexture(tex, TRANSLATION(Translation_Remap + curbasepal, globalpal), CLAMP_NOFILTER_XY, true);
GLInterface.SetModel(m->model, 0, 0, 0);
GLInterface.Draw(DT_Triangles, 0, 0);
GLInterface.SetModel(nullptr, 0, 0, 0);
GLInterface.SetCull(Cull_None);
if (shadowHack)
{
GLInterface.SetDepthFunc(DF_Less);
}
GLInterface.SetIdentityMatrix(Matrix_Model);
return 1;
}
extern int voxlumps[MAXVOXELS];
void (*PolymostProcessVoxels_Callback)(void) = NULL;
void PolymostProcessVoxels(void)
{
if (PolymostProcessVoxels_Callback)
PolymostProcessVoxels_Callback();
if (g_haveVoxels != 1)
return;
g_haveVoxels = 2;
Printf(PRINT_NONOTIFY, "Generating voxel models for Polymost. This may take a while...\n");
for (int i = 0; i < MAXVOXELS; i++)
{
int lumpnum = voxlumps[i];
if (lumpnum > 0)
{
voxmodels[i] = voxload(lumpnum);
if (voxmodels[i])
voxmodels[i]->scale = voxscale[i] * (1.f / 65536.f);
else
Printf("Unable to load voxel from %s\n", fileSystem.GetFileFullPath(lumpnum));
}
}
}
#endif
//---------------------------------------- VOX LIBRARY ENDS ----------------------------------------

View file

@ -74,6 +74,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "v_draw.h"
#include "gi.h"
#include "gamefuncs.h"
#include "hw_voxels.h"
CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -135,6 +136,7 @@ void SetConsoleNotifyBuffer();
bool PreBindTexture(FRenderState* state, FGameTexture*& tex, EUpscaleFlags& flags, int& scaleflags, int& clampmode, int& translation, int& overrideshader);
void PostLoadSetup();
void FontCharCreated(FGameTexture* base, FGameTexture* untranslated, FGameTexture* translated);
void LoadVoxelModels();
DBaseStatusBar* StatusBar;
@ -573,7 +575,7 @@ int GameMain()
G_SaveConfig();
C_DeinitConsole();
V_ClearFonts();
vox_deinit();
voxClear();
TexMan.DeleteAll();
TileFiles.CloseAll(); // delete the texture data before shutting down graphics.
GLInterface.Deinit();
@ -923,6 +925,12 @@ int RunGame()
enginePreInit();
SetupGameButtons();
gameinfo.mBackButton = "engine/graphics/m_back.png";
GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes.
gi->loadPalette();
voxInit();
TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games.
engineInit();
gi->app_init();
CreateStatusBar();
SetDefaultMenuColors();
@ -934,7 +942,15 @@ int RunGame()
V_LoadTranslations(); // loading the translations must be delayed until the palettes have been fully set up.
lookups.postLoadTables();
PostLoadSetup();
videoInit();
lookups.postLoadLookups();
V_Init2();
setVideoMode();
LoadVoxelModels();
GLInterface.Init(screen->GetWidth());
screen->BeginFrame();
screen->SetTextureFilterMode();
setViewport(hud_size);
D_CheckNetGame();
UpdateGenericUI(ui_generic);
@ -1002,7 +1018,7 @@ void updatePauseStatus()
//
//==========================================================================
void PolymostProcessVoxels(void);
void LoadVoxelModels(void);
void setVideoMode()
{
@ -1013,24 +1029,6 @@ void setVideoMode()
videoClearScreen(0);
}
void videoInit()
{
lookups.postLoadLookups();
V_Init2();
setVideoMode();
PolymostProcessVoxels();
GLInterface.Init(screen->GetWidth());
screen->BeginFrame();
screen->SetTextureFilterMode();
setViewport(hud_size);
}
void G_FatalEngineError(void)
{
I_FatalError("There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr);
}
//==========================================================================
//
//

View file

@ -213,7 +213,6 @@ void S_PauseSound(bool notmusic, bool notsfx);
void S_ResumeSound(bool notsfx);
void S_SetSoundPaused(int state);
void G_FatalEngineError(void);
enum
{
MaxSmoothRatio = FRACUNIT

View file

@ -148,28 +148,6 @@ bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnu
return true;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
bool spriteIsModelOrVoxel(const spritetype * tspr)
{
if ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].flags & SPREXT_NOTMD)
return false;
if (hw_models)
{
auto& mdinfo = tile2model[Ptile2tile(tspr->picnum, tspr->pal)];
if (mdinfo.modelid >= 0 && mdinfo.framenum >= 0) return true;
}
auto slabalign = (tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB;
if (r_voxels && !slabalign && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) return true;
return (slabalign && voxmodels[tspr->picnum]);
}
//==========================================================================
//
// note that this returns values in renderer coordinate space with inverted sign!

View file

@ -7,7 +7,6 @@
extern int cameradist, cameraclock;
bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnum, binangle ang, fixedhoriz horiz, double const smoothratio);
bool spriteIsModelOrVoxel(const spritetype* tspr);
void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz);
void setWallSectors();
void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render = false);

View file

@ -0,0 +1,114 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2021 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** hw_voxels.cpp
**
** voxel handling.
**
**/
#include "build.h"
#include "voxels.h"
#include "hw_voxels.h"
#include "gamecontrol.h"
int16_t tiletovox[MAXTILES];
static int voxlumps[MAXVOXELS];
float voxscale[MAXVOXELS];
voxmodel_t* voxmodels[MAXVOXELS];
FixedBitArray<MAXVOXELS> voxrotate;
void voxInit()
{
for (auto& v : tiletovox) v = -1;
for (auto& v : voxscale) v = 1.f;
voxrotate.Zero();
}
void voxClear()
{
for (auto& vox : voxmodels)
{
if (vox) delete vox;
vox = nullptr;
}
}
int voxDefine(int voxindex, const char* filename)
{
if ((unsigned)voxindex >= MAXVOXELS)
return -1;
int i = fileSystem.FindFile(filename);
voxlumps[voxindex] = i;
return i < 0 ? -1 : 0;
}
static voxmodel_t* voxload(int lumpnum)
{
FVoxel* voxel = R_LoadKVX(lumpnum);
if (voxel != nullptr)
{
voxmodel_t* vm = new voxmodel_t;
*vm = {};
auto pivot = voxel->Mips[0].Pivot;
vm->mdnum = 1; //VOXel model id
vm->scale = vm->bscale = 1.f;
vm->piv.x = float(pivot.X);
vm->piv.y = float(pivot.Y);
vm->piv.z = float(pivot.Z);
vm->siz.x = voxel->Mips[0].SizeX;
vm->siz.y = voxel->Mips[0].SizeY;
vm->siz.z = voxel->Mips[0].SizeZ;
vm->is8bit = true;
voxel->Mips[0].Pivot.Zero(); // Needs to be taken out of the voxel data because it gets baked into the vertex buffer which we cannot use here.
vm->model = new FVoxelModel(voxel, true);
return vm;
}
return nullptr;
}
void LoadVoxelModels()
{
for (int i = 0; i < MAXVOXELS; i++)
{
int lumpnum = voxlumps[i];
if (lumpnum > 0)
{
voxmodels[i] = voxload(lumpnum);
if (voxmodels[i])
voxmodels[i]->scale = voxscale[i];
else
Printf("Unable to load voxel from %s\n", fileSystem.GetFileFullPath(lumpnum));
}
else
{
auto index = fileSystem.FindResource(i, "KVX");
if (index >= 0)
{
voxmodels[i] = voxload(index);
}
}
}
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <stdint.h>
#include "mdsprite.h"
// We still need the relation to mdmodel_t as long as the model code hasn't been redone.
struct voxmodel_t : public mdmodel_t
{
FVoxelModel* model = nullptr;
vec3_t siz;
vec3f_t piv;
int32_t is8bit;
};
extern int16_t tiletovox[];
extern float voxscale[];
extern voxmodel_t* voxmodels[MAXVOXELS];
extern FixedBitArray<MAXVOXELS> voxrotate;
void voxInit();
void voxClear();
int voxDefine(int voxindex, const char* filename);

View file

@ -40,6 +40,7 @@
#include "gamefuncs.h"
#include "hw_portal.h"
#include "gamestruct.h"
#include "hw_voxels.h"
//==========================================================================

View file

@ -41,6 +41,7 @@
#include "gamecvars.h"
#include "gamestruct.h"
#include "automap.h"
#include "hw_voxels.h"
EXTERN_CVAR(Float, r_visibility)
CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -300,14 +301,14 @@ void HWDrawInfo::DispatchSprites()
{
HWSprite hwsprite;
int num = tiletovox[tspr->picnum];
if (hwsprite.ProcessVoxel(this, voxmodels[tiletovox[tspr->picnum]], tspr, &sector[tspr->sectnum], voxrotate[num >> 3] & (1 << (num & 7))))
if (hwsprite.ProcessVoxel(this, voxmodels[tiletovox[tspr->picnum]], tspr, &sector[tspr->sectnum], voxrotate[num]))
continue;
}
else if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB && tspr->picnum < MAXVOXELS && voxmodels[tspr->picnum])
{
HWSprite hwsprite;
int num = tspr->picnum;
hwsprite.ProcessVoxel(this, voxmodels[tspr->picnum], tspr, &sector[tspr->sectnum], voxrotate[num >> 3] & (1 << (num & 7)));
hwsprite.ProcessVoxel(this, voxmodels[tspr->picnum], tspr, &sector[tspr->sectnum], voxrotate[num]);
continue;
}
}

View file

@ -26,6 +26,7 @@ struct FDynLightData;
class VSMatrix;
struct FSpriteModelFrame;
class FRenderState;
struct voxmodel_t;
struct HWSectorPlane
{

View file

@ -44,6 +44,7 @@
#include "hw_renderstate.h"
#include "hw_models.h"
#include "hw_viewpointbuffer.h"
#include "hw_voxels.h"
extern PalEntry GlobalMapFog;
extern float GlobalFogDensity;
@ -487,7 +488,7 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, se
if ((spr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate)
{
int myclock = (PlayClock << 3) + MulScale(4 << 3, (int)di->Viewpoint.TicFrac, 16);
ang = (ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common.
ang = (ang + myclock) & 2047;
}

View file

@ -646,7 +646,6 @@ void SerializeMap(FSerializer& arc)
("numshades", numshades) // is this really needed?
("visibility", g_visibility)
("parallaxtype", parallaxtype)
("parallaxvisibility", parallaxvisibility)
("parallaxyo", parallaxyoffs_override)
("parallaxys", parallaxyscale_override)
("pskybits", pskybits_override)

View file

@ -47,6 +47,7 @@
#include "c_dispatch.h"
#include "sc_man.h"
#include "gamestruct.h"
#include "hw_voxels.h"
#include "hw_renderstate.h"
@ -648,7 +649,7 @@ void artSetupMapArt(const char* filename)
void tileDelete(int tile)
{
TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TexMan.GameByIndex(0);
vox_undefine(tile);
tiletovox[tile] = -1; // clear the link but don't clear the voxel. It may be in use for another tile.
md_undefinetile(tile);
}

View file

@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "v_2ddrawer.h"
#include "v_video.h"
#include "v_font.h"
#include "hw_voxels.h"
#include "glbackend/glbackend.h"
BEGIN_BLD_NS

View file

@ -465,9 +465,6 @@ void GameInterface::app_init()
HookReplaceFunctions();
Printf(PRINT_NONOTIFY, "Initializing Build 3D engine\n");
engineInit();
Printf(PRINT_NONOTIFY, "Loading tiles\n");
if (!tileInit(0, NULL))
I_FatalError("TILES###.ART files not found");

View file

@ -122,7 +122,6 @@ extern short voxelIndex[MAXTILES];
extern int nPrecacheCount;
int tileInit(char a1, const char *a2);
void tileProcessGLVoxels(void);
void tilePreloadTile(int nTile);
void tilePrecacheTile(int nTile, int nType, HitList& hits);

View file

@ -44,14 +44,11 @@ char surfType[kMaxTiles];
signed char tileShade[kMaxTiles];
short voxelIndex[kMaxTiles];
const char *pzBaseFileName = "TILES%03i.ART"; //"TILES%03i.ART";
int tileInit(char a1, const char *a2)
{
UNREFERENCED_PARAMETER(a1);
if (artLoaded)
return 1;
TileFiles.artLoadFiles(a2 ? a2 : pzBaseFileName);
for (int i = 0; i < kMaxTiles; i++)
voxelIndex[i] = 0;
@ -81,32 +78,9 @@ int tileInit(char a1, const char *a2)
}
artLoaded = 1;
#ifdef USE_OPENGL
PolymostProcessVoxels_Callback = tileProcessGLVoxels;
#endif
return 1;
}
#ifdef USE_OPENGL
void tileProcessGLVoxels(void)
{
static bool voxInit = false;
if (voxInit)
return;
voxInit = true;
for (int i = 0; i < kMaxVoxels; i++)
{
auto index = fileSystem.FindResource(i, "KVX");
if (index >= 0)
{
voxmodels[i] = voxload(index);
}
}
}
#endif
char tileGetSurfType(int hit)
{
int n = hit & 0x3fff;

View file

@ -230,9 +230,6 @@ static void setupbackdrop()
static void initTiles()
{
if (TileFiles.artLoadFiles("tiles%03i.art") < 0)
I_FatalError("Failed loading art.");
tileDelete(TILE_MIRROR);
skiptile = TILE_W_FORCEFIELD + 1;
@ -310,9 +307,6 @@ void GameInterface::app_init()
OnEvent(EVENT_INIT);
if (engineInit())
G_FatalEngineError();
//Net_SendClientInfo();
initTiles();

View file

@ -75,12 +75,6 @@ void ResetEngine()
void InstallEngine()
{
TileFiles.LoadArtSet("tiles%03d.art");
if (engineInit())
{
G_FatalEngineError();
}
uploadCinemaPalettes();
LoadPaletteLookups();
}

View file

@ -199,7 +199,6 @@ void GameInterface::app_init()
registerosdcommands();
engineInit();
auto pal = fileSystem.LoadFile("3drealms.pal", 0);
if (pal.Size() >= 768)
{
@ -220,8 +219,6 @@ void GameInterface::app_init()
"the full version. Read the Ordering Info screens for details.");
}
TileFiles.LoadArtSet("tiles%03d.art");
//Connect();
SortBreakInfo();
parallaxtype = 1;

View file

@ -40,6 +40,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "razemenu.h"
#include "quotemgr.h"
#include "mapinfo.h"
#include "hw_voxels.h"
BEGIN_SW_NS
@ -231,7 +232,7 @@ void LoadKVXFromScript(const char* filename)
GetToken(false);
// Load the voxel file into memory
if (!qloadkvx(lNumber,token))
if (!voxDefine(lNumber,token))
{
// Store the sprite and voxel numbers for later use
aVoxelArray[lTile].Voxel = lNumber; // Voxel num