139 lines
4.5 KiB
C
139 lines
4.5 KiB
C
|
/*
|
||
|
mod_terrain_create terrorgen; edit maps/terrorgen.hmp; map terrorgen
|
||
|
you can use mod_terrain_convert to generate+save the entire map for redistribution to people without this particular plugin version, ensuring longevity.
|
||
|
(this paticular command was meant to load+save the entire map, once mod_terrain_savever 2 is default...)
|
||
|
|
||
|
FIXME: no way to speciffy which gen plugin to use for a particular map
|
||
|
*/
|
||
|
|
||
|
#include "../plugin.h"
|
||
|
#include "glquake.h"
|
||
|
#include "com_mesh.h"
|
||
|
#include "gl_terrain.h"
|
||
|
|
||
|
static terrainfuncs_t *terr;
|
||
|
static modplugfuncs_t *modfuncs;
|
||
|
|
||
|
static void TerrorGen_GenerateOne(heightmap_t *hm, int sx, int sy, hmsection_t *s)
|
||
|
{
|
||
|
int x,y,i;
|
||
|
qbyte *lm;
|
||
|
|
||
|
s->flags |= TSF_RELIGHT;
|
||
|
|
||
|
//pick the textures to blend between. I'm just hardcoding shit here. this is meant to be some sort example.
|
||
|
Q_strlcpy(s->texname[0], "city4_2", sizeof(s->texname[0]));
|
||
|
Q_strlcpy(s->texname[1], "ground1_2", sizeof(s->texname[1]));
|
||
|
Q_strlcpy(s->texname[2], "ground1_8", sizeof(s->texname[2]));
|
||
|
Q_strlcpy(s->texname[3], "ground1_1", sizeof(s->texname[3]));
|
||
|
|
||
|
for (y = 0, i=0; y < SECTHEIGHTSIZE; y++)
|
||
|
for (x = 0; x < SECTHEIGHTSIZE; x++, i++)
|
||
|
{
|
||
|
//calculate where it is in worldspace, if that's useful to you.
|
||
|
float wx = hm->sectionsize*(sx + x/(float)(SECTHEIGHTSIZE-1));
|
||
|
float wy = hm->sectionsize*(sy + y/(float)(SECTHEIGHTSIZE-1));
|
||
|
|
||
|
//many shallow mounds, on a grid.
|
||
|
s->heights[i] = 128*sin(wx * (2*M_PI/1024)) * sin(wy * (2*M_PI/1024));
|
||
|
|
||
|
//calculate the RGBA tint. these are floats, so you can oversaturate.
|
||
|
s->colours[i][0] = 1;
|
||
|
s->colours[i][1] = 1;
|
||
|
s->colours[i][2] = 1;
|
||
|
s->colours[i][3] = 1;
|
||
|
}
|
||
|
|
||
|
//make sure there's lightmap storage available
|
||
|
terr->InitLightmap(s, /*fill with default values*/true);
|
||
|
lm = terr->GetLightmap(s, 0, /*flag as edited*/true);
|
||
|
if (lm)
|
||
|
{ //pleaseworkpleaseworkpleasework
|
||
|
for (y = 0; y < SECTTEXSIZE; y++, lm += (HMLMSTRIDE)*4)
|
||
|
for (x = 0; x < SECTTEXSIZE; x++)
|
||
|
{
|
||
|
//calculate where it is in worldspace, if that's useful to you.
|
||
|
float wx = hm->sectionsize*(sx + x/(float)(SECTTEXSIZE-1));
|
||
|
float wy = hm->sectionsize*(sy + y/(float)(SECTTEXSIZE-1));
|
||
|
|
||
|
//calc which texture to use
|
||
|
//adds to 1, with texture[3] taking the remainder.
|
||
|
lm[x*4+0] = max(0, 255 - 255*fabs(wx/1024));
|
||
|
lm[x*4+1] = max(0, 255 - 255*fabs(wy/1024));
|
||
|
lm[x*4+2] = min(lm[x*4+0],lm[x*4+1]);
|
||
|
lm[x*4+0] -= lm[x*4+2];
|
||
|
lm[x*4+1] -= lm[x*4+2];
|
||
|
|
||
|
//logically: lm[x*4+3] = 255-(lm[x*4+0]+lm[x*4+1]+lm[x*4+2]);
|
||
|
//however, the fourth channel is actually used as a lighting multiplier.
|
||
|
lm[x*4+3] = 255;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//insert the occasional mesh...
|
||
|
if ((sx&3) == 0 && (sy&3) == 0)
|
||
|
{
|
||
|
vec3_t ang, org, axis[3];
|
||
|
org[0] = hm->sectionsize*sx;
|
||
|
org[1] = hm->sectionsize*sy;
|
||
|
org[2] = 128;
|
||
|
VectorClear(ang);
|
||
|
ang[0] = sy*12.5; //lul
|
||
|
ang[1] = sx*12.5;
|
||
|
modfuncs->AngleVectors(ang, axis[0], axis[1], axis[2]);
|
||
|
VectorNegate(axis[1],axis[1]); //axis[1] needs to be left, not right. silly quakeisms.
|
||
|
|
||
|
//obviously you can insert mdls instead... preferably do that!
|
||
|
terr->AddMesh(hm, TGS_TRYLOAD, NULL, "maps/dm4.bsp", org, axis, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define GENBLOCKSIZE 1
|
||
|
static qboolean QDECL TerrorGen_GenerateBlock(heightmap_t *hm, int sx, int sy, unsigned int tgsflags)
|
||
|
{
|
||
|
hmsection_t *sect[GENBLOCKSIZE*GENBLOCKSIZE];
|
||
|
int mx = sx & ~(GENBLOCKSIZE-1);
|
||
|
int my = sy & ~(GENBLOCKSIZE-1);
|
||
|
|
||
|
if (!terr->GenerateSections(hm, mx, my, GENBLOCKSIZE, sect))
|
||
|
return false;
|
||
|
|
||
|
for (sy = 0; sy < GENBLOCKSIZE; sy++)
|
||
|
{
|
||
|
for (sx = 0; sx < GENBLOCKSIZE; sx++)
|
||
|
{
|
||
|
if (!sect[sx + sy*GENBLOCKSIZE])
|
||
|
continue; //already in memory.
|
||
|
|
||
|
TerrorGen_GenerateOne(hm, mx+sx-CHUNKBIAS, my+sy-CHUNKBIAS, sect[sx + sy*GENBLOCKSIZE]);
|
||
|
terr->FinishedSection(sect[sx + sy*GENBLOCKSIZE], true);
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static qintptr_t TerrorGen_Shutdown(qintptr_t *args)
|
||
|
{ //if its still us, make sure there's no dangling pointers.
|
||
|
if (terr->AutogenerateSection == TerrorGen_GenerateBlock)
|
||
|
terr->AutogenerateSection = NULL;
|
||
|
return true;
|
||
|
}
|
||
|
qintptr_t Plug_Init(qintptr_t *args)
|
||
|
{
|
||
|
if (CHECKBUILTIN(Mod_GetPluginModelFuncs))
|
||
|
{
|
||
|
modfuncs = pMod_GetPluginModelFuncs(sizeof(modplugfuncs_t));
|
||
|
if (modfuncs && modfuncs->version < MODPLUGFUNCS_VERSION)
|
||
|
modfuncs = NULL;
|
||
|
}
|
||
|
|
||
|
if (modfuncs && modfuncs->GetTerrainFuncs)
|
||
|
terr = modfuncs->GetTerrainFuncs();
|
||
|
if (!terr)
|
||
|
return false;
|
||
|
if (!Plug_Export("Shutdown", TerrorGen_Shutdown))
|
||
|
return false;
|
||
|
|
||
|
terr->AutogenerateSection = TerrorGen_GenerateBlock;
|
||
|
return true;
|
||
|
}
|