MK Autogen Materials Fix
by Trenton Shaffer · 01/05/2009 (7:06 am) · 1 comments
The Resource
The Modernization Kit is a great resource for TGE. This resource only applies to TGE 1.5.2 with the Modernization Kit applied.
The Feature
Any of you that have implemented MK have surely come across the automatic generating normal maps for interiors script. For those of you who have not, there is a non-production AutoGen Materials script that is implemented in MK to get you up and going quick with normal mapping for your interiors.
The script automatically scans your interior texture maps, and generates normal maps for each interior. In addition it creates a file called 'autogenMatList.cs' in each interior folder which holds the material list for the normal maps.
The Issue
I thought this was a cool feature. I would simply let the script create my normal maps and the associated material list. Then I could open up the normal maps and edit them in Photoshop to achieve the desired effect.
Here is where I bumped into an issue. The autogen materials script automagically creates the normal maps each time the script runs and therefore overwrites the normal map each time it is ran.
The Fix/Hack
This is where my fix/hack comes into play. This fix will prevent your engine from auto-generating and overwriting your normal maps if they already exist. If they don't exist, it still automatically creates the normal map.
If you want them automatically generated again, simply go delete the PNG normal map(s) from the appropriate Interiors folder.
========================
Open mkInterior.cpp:
Find the following function at the bottom of mkInterior.cpp:
Replace the entire function with the following code:
NOTE: All changes are commented with 'TS AUTOGEN_NORMALMAP FIX'.
That's it. Recompile your engine and you can use the AutoGen Materials Script to automagically create your normal maps and associated material lists. Then just edit each auto-created normal map with your favorite image editor and save it. The next time you start torque it will be using your custom normal map.
Enjoy!
The Modernization Kit is a great resource for TGE. This resource only applies to TGE 1.5.2 with the Modernization Kit applied.
The Feature
Any of you that have implemented MK have surely come across the automatic generating normal maps for interiors script. For those of you who have not, there is a non-production AutoGen Materials script that is implemented in MK to get you up and going quick with normal mapping for your interiors.
The script automatically scans your interior texture maps, and generates normal maps for each interior. In addition it creates a file called 'autogenMatList.cs' in each interior folder which holds the material list for the normal maps.
The Issue
I thought this was a cool feature. I would simply let the script create my normal maps and the associated material list. Then I could open up the normal maps and edit them in Photoshop to achieve the desired effect.
Here is where I bumped into an issue. The autogen materials script automagically creates the normal maps each time the script runs and therefore overwrites the normal map each time it is ran.
The Fix/Hack
This is where my fix/hack comes into play. This fix will prevent your engine from auto-generating and overwriting your normal maps if they already exist. If they don't exist, it still automatically creates the normal map.
If you want them automatically generated again, simply go delete the PNG normal map(s) from the appropriate Interiors folder.
========================
Open mkInterior.cpp:
Find the following function at the bottom of mkInterior.cpp:
void mkInterior::generateMaterial(TextureHandle& handle, const char* name, const char* path, FileStream &pMapStream)
{
#ifdef MK_AUTOGEN_NORMALMAP
...
...
...
#endif
}Replace the entire function with the following code:
void mkInterior::generateMaterial(TextureHandle& handle, const char* name, const char* path, FileStream &pMapStream)
{
// TS AUTOGEN_NORMALMAP FIX -- START
char filechecker[256];
bool filecheckedexists;
filecheckedexists = false;
dSprintf(filechecker, sizeof(filechecker), "%s/%s_height_auto.png",path, name);
if(ResourceManager->getPathOf(filechecker))
{
Con::printf("FOUND: %s, skipping normal map generation", filechecker);
filecheckedexists = true;
}
// TS AUTOGEN_NORMALMAP FIX -- END
#ifdef MK_AUTOGEN_NORMALMAP
U32 texWidth = handle.getWidth();
U32 texHeight = handle.getHeight();
// Ya, no nonexistant textures.
if(texWidth == 0 || texHeight == 0)
return;
if(!filecheckedexists) // <--ADDED: TS AUTOGEN_NORMALMAP FIX
Con::printf("Generating material for texture %s, width %i, height %i", name, texWidth, texHeight);
RenderTextureFormat testFormat(RGBA8, Depth16, None, Stencil0, 4, true, false);
RenderTextureFormat bestFit;
RenderTextureManager->getClosestMatch(testFormat, bestFit);
RenderTexture *heightmap = RenderTextureManager->createRenderTexture(texWidth, texHeight, bestFit);
RenderTexture *nmap = RenderTextureManager->createRenderTexture(texWidth, texHeight, bestFit);
Material* heightmapCreator = MaterialManager->findMaterialByName("heightmapCreator");
Material *nmapCreator = MaterialManager->findMaterialByName("nmapCreator");
// It'd be bad if we didn't have our materials
if(!heightmapCreator || !nmapCreator || !heightmapCreator->getActiveShader() || !nmapCreator->getActiveShader())
return;
// Generate the heightmap (blurred greyscale)
RenderTextureManager->renderToTexture(heightmap);
heightmapCreator->bind();
ShaderManager->setParameter("TextureSize", F32(texWidth), F32(texHeight));
glBindTexture(GL_TEXTURE_2D, handle.getGLName());
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(0, 1);
glVertex2f(-1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 1);
glTexCoord2f(1, 0);
glVertex2f(1, -1);
glEnd();
// Generate the normal map from the blurred heightmap
// Makes parallax mapping (and normal mapping) look
// so much nicer.
RenderTextureManager->renderToTexture(nmap);
heightmap->bindToUse(0);
nmapCreator->bind();
ShaderManager->setParameter("TextureSize", F32(texWidth), F32(texHeight));
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(0, 1);
glVertex2f(-1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 1);
glTexCoord2f(1, 0);
glVertex2f(1, -1);
glEnd();
RenderTextureManager->renderToTexture(NULL);
// I forgot this at first. Bad things happened. DON'T REMOVE IT!!!
ShaderManager->unbindShader();
// TS AUTOGEN_NORMALMAP FIX -- START
if(!filecheckedexists)
{// TS AUTOGEN_NORMALMAP FIX -- END
FileStream fStream;
char texturePath[256];
// Download our fine work for saving.
GBitmap *nmapTexture = nmap->download();
dSprintf(texturePath, sizeof(texturePath), "%s/%s_height_auto.png",path, name);
// Life sucks if we can't save all of our work
if(!fStream.open(texturePath, FileStream::Write))
{
Con::printf("Failed to open file '%s'.", texturePath);
return;
}
// Write a PNG
nmapTexture->writePNG(fStream);
fStream.close();
delete nmapTexture;
}// <--ADDED: TS AUTOGEN_NORMALMAP FIX
// Bah, we don't need anything anymore
RenderTextureManager->deleteRenderTexture(nmap);
RenderTextureManager->deleteRenderTexture(heightmap);
// Save the script command to load this next time.
char nMapPath[256];
char texPath[256];
dSprintf(nMapPath, sizeof(nMapPath), "%s/%s_height_auto",path, name);
dSprintf(texPath, sizeof(texPath), "%s/%s",path, name);
char scriptCommand[2048];
dSprintf(scriptCommand, sizeof(scriptCommand), "new Material()\n{\n mapTo = \"%s\";\n Shader20 = InteriorParallax20;\n textures[0] = \"Lightmap\";\n textures[1] = \"%s\";\n textures[2] = \"%s\";\n textures[3] = \"Fog\";\n\n samplers[0] = \"LightMap\";\n samplers[1] = \"BaseTexture\";\n samplers[2] = \"NormalMap\";\n samplers[3] = \"FogTexture\";\n};\n\n", texPath, texPath, nMapPath);
pMapStream.write(dStrlen(scriptCommand), scriptCommand);
Con::evaluate(scriptCommand);
#elif defined(MK_AUTOGEN_MATERIALS)
char texPath[256];
dSprintf(texPath, sizeof(texPath), "%s/%s",path, name);
char scriptCommand[2048];
dSprintf(scriptCommand, sizeof(scriptCommand), "new Material()\n{\n mapTo = \"%s\";\n Shader20 = InteriorFF20;\n textures[0] = \"Lightmap\";\n textures[1] = \"%s\";\n textures[3] = \"Fog\";\n\n samplers[0] = \"LightMap\";\n samplers[1] = \"BaseTexture\";\n samplers[3] = \"FogTexture\";\n};\n\n", texPath, texPath);
pMapStream.write(dStrlen(scriptCommand), scriptCommand);
Con::evaluate(scriptCommand);
#endif
}NOTE: All changes are commented with 'TS AUTOGEN_NORMALMAP FIX'.
That's it. Recompile your engine and you can use the AutoGen Materials Script to automagically create your normal maps and associated material lists. Then just edit each auto-created normal map with your favorite image editor and save it. The next time you start torque it will be using your custom normal map.
Enjoy!
About the author
Torque 3D Owner Daniel Buckmaster