hwToonShader_NV20/MNormalMapConverter.cpp

hwToonShader_NV20/MNormalMapConverter.cpp
//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related
// material (collectively the "Data") in these files contain unpublished
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its
// licensors, which is protected by U.S. and Canadian federal copyright
// law and by international treaties.
//
// The Data is provided for use exclusively by You. You have the right
// to use, modify, and incorporate this Data into other products for
// purposes authorized by the Autodesk software license agreement,
// without fee.
//
// The copyright notices in the Software and this entire statement,
// including the above license grant, this restriction and the
// following disclaimer, must be included in all copies of the
// Software, in whole or in part, and all derivative works of
// the Software, unless such copies or derivative works are solely
// in the form of machine-executable object code generated by a
// source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
// PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR
// TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS
// BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
// DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK
// AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY
// OR PROBABILITY OF SUCH DAMAGES.
//
// ==========================================================================
//+
// DESCRIPTION:
// Some utilities to do file format conversions and others ...
//
#include <maya/MStatus.h>
#include <math.h>
#include "MNormalMapConverter.h"
// Convert the heightfield texture to its corresponding normal map texture
//
bool MNormalMapConverter::convertToNormalMap(
unsigned char* inImagePtr,
unsigned int width,
unsigned int height,
OutFormatType outputPixelFormat,
float bumpScale,
unsigned char* outImagePtr )
{
bool isOK = true;
// Firewall: The input image should not be a NULL pointer,
//
if( NULL == inImagePtr ) return false;
// No output file specified: convert in place
//
if( NULL == outImagePtr )
{
convertToNormalMap_InPlace( inImagePtr, width, height, outputPixelFormat, bumpScale );
}
else
{
if( outputPixelFormat == RGBA ) {
//
// Not implemented yet
//
// similar to the convertToNormalMap_InPlace but we store
// the resulting texture in the outImagePtr and not
// in the inImagePtr texture
//
}
else if( outputPixelFormat == HILO ) {
// Not implemented yet
}
else {
isOK = false;
}
}
return isOK;
}
// The heightfield texture inImage will be replaced from grey levels in RGBA
// to the normal map values as specified by the pixel format
//
bool MNormalMapConverter::convertToNormalMap_InPlace(
unsigned char* inImagePtr,
unsigned int width,
unsigned int height,
OutFormatType outputPixelFormat,
float bumpScale )
{
bool isOK = true;
if( outputPixelFormat == RGBA ) {
bumpScale /= 255.0f; // will be used on unsignedChar
unsigned int widthMinus1 = width - 1;
unsigned int heightMinus1 = height - 1;
unsigned int offset = (4 * width); // = sizeof(rgba) * width
// ==================
// Process the texels
// ==================
// Get the current pointer to the starting texel at (0,0)
//
unsigned char* imagePtr = inImagePtr;
// For each rows (except the last one)
//
unsigned int m, n;
for( m=0; m<heightMinus1; m++ )
{
// Process the texel in each column of this row
//
for( n=0; n<widthMinus1; n++ )
{
float deltaU = bumpScale * (float)(imagePtr[0] - imagePtr[4]);
float deltaV = bumpScale * (float)(imagePtr[0] - imagePtr[offset]);
// Normalize (deltaU, deltaV, 1.)
float sqlen = deltaU*deltaU + deltaV*deltaV + 1.0f;
float rclen = 1.0f / sqrtf( sqlen );
float nx = deltaU * rclen;
float ny = deltaV * rclen;
float nz = rclen;
// Store the vector in red, green, blue
*(imagePtr++) = (unsigned char) ((nx + 1.0f) * 127.5f);
*(imagePtr++) = (unsigned char) ((ny + 1.0f) * 127.5f);
*(imagePtr++) = (unsigned char) ((nz + 1.0f) * 127.5f);
// reset the alpha
*(imagePtr++) = 255;
}
// At the end of the row, just copy the last value. One
// could implement wraping instead.
*(imagePtr++) = imagePtr[-4];
*(imagePtr++) = imagePtr[-4];
*(imagePtr++) = imagePtr[-4];
*(imagePtr++) = 255;
}
// Fill in the last row (copy from the (last-1) row)
// memcpy is the faster loop when memory is aligned.
memcpy(imagePtr, imagePtr-offset, width*4);
}
else if( outputPixelFormat == HILO ) {
// Not implemented yet
}
else {
isOK = false;
}
return isOK;
}
bool MNormalMapConverter::convertToHeightMap(
unsigned char* inImagePtr,
unsigned int width,
unsigned int height,
OutFormatType outputPixelFormat,
float heightScale,
unsigned char* outImagePtr)
{
// Not implemented yet
//
return false;
}