/* 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; }