/*
===========================================================================
IcedTech GPL Source Code
Copyright (C) 2019 Real Vector Math Studios(Justin Marshall).
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the IcedTech GPL Source Code ("IcedTech GPL Source Code").
IcedTech GPL Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IcedTech GPL Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with IcedTech GPL Source Code. If not, see .
In addition, the IcedTech GPL Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IcedTech GPL Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "precompiled.h"
#pragma hdrstop
#include "MegaGen.h"
/*
===============================================
MegaGen Tool
Builds the megatexture source. Why? Because doing it in Photoshop causes computers to explode :).
===============================================
*/
/*
===================
WriteTargaHeader
===================
*/
void WriteTargaHeader(idFile *megaTarga, int width, int height)
{
byte buffer[18];
int i;
memset(buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = width & 255;
buffer[13] = width >> 8;
buffer[14] = height & 255;
buffer[15] = height >> 8;
buffer[16] = 32; // pixel size
megaTarga->Write(buffer, sizeof(buffer));
}
/*
===================
LerpPixel
===================
*/
byte LerpPixel(byte start, byte end, byte mask) {
float t = ((float)mask) / 255.0f;
return (byte)((1 - t)*start + t * end);
}
/*
===================
R_GetMegaLayerImagePixel
===================
*/
byte *R_GetMegaLayerImagePixel(MegaLayerImage_t *layer, int x, int y) {
return &layer->data[(y * layer->width * 4) + (x * 4)];
}
/*
===================
EvaluateMegaLayer
===================
*/
void EvaluateMegaLayer(int megaSize, int megaScanLine, MegaLayer *megaLayer, byte *megaScratch) {
float maskScanlineScale = (float)megaScanLine / (float)megaSize;
for (int i = 0; i < megaSize; i++)
{
int albedoX = i % megaLayer->albedoImage.width;
int albedoY = megaScanLine % megaLayer->albedoImage.height;
float maskColumnScale = (float)i / (float)megaSize;
int maskX = maskColumnScale * (float)megaLayer->maskImage.width;
int maskY = maskScanlineScale * (float)megaLayer->maskImage.height;
byte *megaLayerAlbedoData = R_GetMegaLayerImagePixel(&megaLayer->albedoImage, albedoX, albedoY);
byte *megaLayerMaskData = R_GetMegaLayerImagePixel(&megaLayer->maskImage, maskX, maskY);
byte mask = megaLayerMaskData[0];
// Lerp MegaPixel against the current megaScalinePixel based on the mask.
megaScratch[(i * 4) + 0] = LerpPixel(megaScratch[(i * 4) + 0], megaLayerAlbedoData[2], mask);
megaScratch[(i * 4) + 1] = LerpPixel(megaScratch[(i * 4) + 1], megaLayerAlbedoData[1], mask);
megaScratch[(i * 4) + 2] = LerpPixel(megaScratch[(i * 4) + 2], megaLayerAlbedoData[0], mask);
megaScratch[(i * 4) + 3] = LerpPixel(megaScratch[(i * 4) + 3], megaLayerAlbedoData[3], mask);
}
}
/*
===================
BuildMegaProject
===================
*/
void BuildMegaProject(int megaSize, idFile *megaTarga, rvmMegaProject &megaProject) {
idTempArray megaTextureScanLine(megaSize * 4);
idTempArray scratchScanLine(megaSize * 4);
// Write out the targa header
WriteTargaHeader(megaTarga, megaSize, megaSize);
// Walk through each scanline for evaluation.
for (int i = 0; i < megaSize; i++)
{
//common->Printf("Writing scanline %d/%d\n", i, megaSize);
// Iterate over all the layers.
for (int layerId = 0; layerId < megaProject.GetNumMegaLayers(); layerId++)
{
// Evaluate the mega layer.
EvaluateMegaLayer(megaSize, i, megaProject.GetMegaLayer(layerId), scratchScanLine.Ptr());
}
megaTarga->Write(scratchScanLine.Ptr(), megaSize * 4);
}
}
/*
===================
RunMegaGen_f
===================
*/
void RunMegaGen_f(const idCmdArgs &args) {
rvmMegaProject megaProject;
common->SetRefreshOnPrint(true);
if (args.Argc() < 3) {
common->Warning("Usage: megagen \n");
common->SetRefreshOnPrint(false);
return;
}
idStr megaProjectName = va("megagen/%s.megagen", args.Argv(1));
idStr megaTargaName = va("megagen/bin/%s.tga", args.Argv(1));
idFileScoped megaTarga(fileSystem->OpenFileWrite(megaTargaName));
int megaSize = atoi(args.Argv(2));
idParser parser;
// Read the entire mega project off disk.
if (!parser.LoadFile(megaProjectName))
{
common->Warning("Failed to load megaproject %s\n", megaProjectName.c_str());
common->SetRefreshOnPrint(false);
return;
}
parser.SetFlags(DECL_LEXER_FLAGS);
// Parse the mega project.
if (!megaProject.ParseProject(parser))
{
// ParseProject should return what went wrong.
common->SetRefreshOnPrint(false);
return;
}
// Build it!!!!
BuildMegaProject(megaSize, megaTarga, megaProject);
common->Printf("MegaProject built successfully!");
common->SetRefreshOnPrint(false);
}