#include "lensDistortionCallback.h"
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MDagPath.h>
#include <maya/MMatrix.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MImage.h>
#include <maya/MIOStream.h>
#include <maya/MFnCamera.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MColor.h>
#include <maya/MFnPlugin.h>
#include <maya/MHardwareRenderer.h>
#include <maya/MGLdefinitions.h>
#define kFloatEpsilon 1.0e-10
#define kRemoveFlag "-r"
#define kRemoveFlagLong "-remove"
#define kExistFlag "-ex"
#define kExistFlagLong "-exists"
#define kListFlag "-l"
#define kListFlagLong "-list"
lensDistortionCompute* lensDistortionCompute::currentLensDistortionCompute[MAX_MODEL_PANEL];
lensDistortionCallback::lensDistortionCallback()
:
mRemoveOperation( false )
, mExistOperation( false )
, mListOperation( false )
{
}
lensDistortionCallback::~lensDistortionCallback()
{
}
void* lensDistortionCallback::creator()
{
return (void *) (new lensDistortionCallback);
}
MSyntax lensDistortionCallback::newSyntax()
{
syntax.
addFlag( kListFlag, kListFlagLong );
return syntax;
}
{
if ( status != MS::kSuccess ) return status;
{
if ( thisArg == kListFlag || thisArg == kListFlagLong )
{
mListOperation = true;
}
else
{
mRemoveOperation = false;
mExistOperation = false;
mPanelName = argDatabase.commandArgumentString( 0, &status );
}
}
else if ( args.
length() == 2 )
{
if ( thisArg == kRemoveFlag || thisArg == kRemoveFlagLong )
{
mRemoveOperation = true;
mPanelName = argDatabase.flagArgumentString( kRemoveFlag, 0, &status );
}
else if ( thisArg == kExistFlag || thisArg == kExistFlagLong )
{
mExistOperation = true;
mPanelName = argDatabase.flagArgumentString( kExistFlag, 0, &status );
}
}
else
{
}
return MS::kSuccess;
}
{
status = parseArgs(args);
if (status != MS::kSuccess){
displayError( "Argument should have a panel name and proper option" );
return status;
}
if ( mListOperation )
{
status = lensDistortionCompute::listCallback( panelNames );
setResult ( panelNames );
return status;
}
if (status != MS::kSuccess){
displayError( "Specified model panel is not valid!" );
return status;
}
if ( mExistOperation )
{
if ( lensDistortionCompute::panelHasCallback( mPanelName ) )
{
setResult( true );
}
else
{
setResult( false );
}
}
else if ( mRemoveOperation )
{
status = lensDistortionCompute::removeCallbackFromPanel( mPanelName );
}
else
{
status = lensDistortionCompute::addCallbackToPanel( mPanelName );
if ( status == MS::kSuccess )
{
setResult( mPanelName );
}
}
return status;
}
lensDistortionCompute::lensDistortionCompute(
const MString &panelName)
:
mTextureIndex( 0 )
, mTextureWidth( 0 )
, mTextureHeight( 0 )
, mMultipleDrawPassCount( 1 )
{
mPanelName = panelName;
mDeleteId
&lensDistortionCompute::deleteCB,
(void *) this, &status);
if (mDeleteId == 0)
mPreRenderId
&lensDistortionCompute::preRenderCB,
(void *) this, &status);
if (mPreRenderId == 0)
mPostRenderId
&lensDistortionCompute::postRenderCB,
(void *) this, &status);
if (mPostRenderId == 0)
mPreMultipleDrawPassId
&lensDistortionCompute::preMultipleDrawPassCB, (void *) this, &status);
if (mPreMultipleDrawPassId == 0)
mPostMultipleDrawPassId
&lensDistortionCompute::postMultipleDrawPassCB, (void *) this, &status);
if (mPostMultipleDrawPassId == 0)
}
lensDistortionCompute::~lensDistortionCompute()
{
clearCallbacks();
for (unsigned int i=0; i<MAX_MODEL_PANEL; i++)
{
if (currentLensDistortionCompute[i] &&
(currentLensDistortionCompute[i])->getPanelName() == mPanelName)
{
currentLensDistortionCompute[i] = 0;
}
}
if ( mTextureIndex )
{
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
_OPENMAYA_POP_WARNING
if ( pRenderer )
{
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
const MString& backEnd = pRenderer->backEndString();
pRenderer->makeResourceContextCurrent( backEnd );
_OPENMAYA_POP_WARNING
glDeleteTextures( 1, &mTextureIndex );
}
else
{
}
}
}
MStatus lensDistortionCompute::addCallbackToPanel(
MString& pPanelName )
{
bool found = false;
int emptyIndex = -1;
for ( unsigned int i = 0; i < MAX_MODEL_PANEL; i++ )
{
if ( currentLensDistortionCompute[i] )
{
if ( currentLensDistortionCompute[i]->getPanelName() == pPanelName )
{
found = true;
}
}
else
{
emptyIndex = i;
}
}
if ( found )
{
status = MS::kFailure;
}
else if ( emptyIndex == -1 )
{
status = MS::kFailure;
}
else
{
currentLensDistortionCompute[emptyIndex] = new lensDistortionCompute( pPanelName );
status = MS::kSuccess;
}
return status;
}
lensDistortionCompute::removeCallbackFromPanel(
MString& pPanelName )
{
for ( unsigned int i = 0; i < MAX_MODEL_PANEL; i++ )
{
if ( currentLensDistortionCompute[i] &&
currentLensDistortionCompute[i]->getPanelName() == pPanelName )
{
delete currentLensDistortionCompute[i];
currentLensDistortionCompute[i] = NULL;
return MS::kSuccess;
}
}
return MS::kFailure;
}
bool
lensDistortionCompute::panelHasCallback(
MString& pPanelName )
{
for ( unsigned int i = 0; i < MAX_MODEL_PANEL; i++ )
{
if ( currentLensDistortionCompute[i] &&
(currentLensDistortionCompute[i])->getPanelName() == pPanelName )
{
return true;
}
}
return false;
}
lensDistortionCompute::listCallback(
MStringArray& pPanelNames )
{
for ( unsigned int i = 0; i < MAX_MODEL_PANEL; i++ )
{
if ( currentLensDistortionCompute[i])
{
pPanelNames.
append( (currentLensDistortionCompute[i])->getPanelName() );
}
}
return MS::kSuccess;
}
void lensDistortionCompute::clearCallbacks()
{
if (mDeleteId)
if (mPreRenderId)
if (mPostRenderId)
if (mPreMultipleDrawPassId)
if (mPostMultipleDrawPassId)
}
void lensDistortionCompute::deleteCB(
const MString& panelName,
void * data)
{
lensDistortionCompute *thisCompute = (lensDistortionCompute *) data;
if ( panelName != thisCompute->mPanelName )
{
}
delete thisCompute;
}
void lensDistortionCompute::preRenderCB(
const MString& panelName,
void * data)
{
lensDistortionCompute *thisCompute = (lensDistortionCompute *) data;
if (!thisCompute)
return;
if (status != MS::kSuccess) return;
thisCompute->mObjectDisplayState = thisCompute->mCurrentView.objectDisplay();
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
thisCompute->mMultipleDrawPassCount = thisCompute->mCurrentView.multipleDrawPassCount();
thisCompute->mCurrentView.setMultipleDrawEnable( true );
thisCompute->mCurrentView.setMultipleDrawPassCount( 2 );
_OPENMAYA_POP_WARNING
}
void lensDistortionCompute::postRenderCB(
const MString& panelName,
void * data)
{
lensDistortionCompute *thisCompute = (lensDistortionCompute *) data;
if (!thisCompute)
return;
thisCompute->draw();
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
thisCompute->mCurrentView.setMultipleDrawEnable( false );
thisCompute->mCurrentView.setObjectDisplay( thisCompute->mObjectDisplayState );
thisCompute->mCurrentView.setMultipleDrawPassCount( thisCompute->mMultipleDrawPassCount );
_OPENMAYA_POP_WARNING
}
void
lensDistortionCompute::preMultipleDrawPassCB(
const MString& pPanelName,
unsigned int passIndex,
void * data)
{
lensDistortionCompute *thisCompute = (lensDistortionCompute *) data;
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
thisCompute->mCurrentView.beginGL();
_OPENMAYA_POP_WARNING
MColor currentBackgroundColor = thisCompute->mCurrentView.backgroundColor();
if( passIndex == 0 )
{
glClearColor( currentBackgroundColor.r, currentBackgroundColor.g, currentBackgroundColor.b, 0.0 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
else
{
glClearColor( currentBackgroundColor.r, currentBackgroundColor.g, currentBackgroundColor.b, currentBackgroundColor.a );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
thisCompute->mCurrentView.endGL();
_OPENMAYA_POP_WARNING
}
void
lensDistortionCompute::postMultipleDrawPassCB(
const MString& pPanelName,
unsigned int passIndex,
void * data)
{
lensDistortionCompute *thisCompute = (lensDistortionCompute *) data;
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
thisCompute->mCurrentView.beginGL();
if ( passIndex == 0 )
{
MStatus status = thisCompute->mCurrentView.readColorBuffer( thisCompute->mPrimaryBuffer,
true );
if ( status != MS::kSuccess )
{
MGlobal::displayError(
"Storing rendering result to buffer failed because of memory shortage. Please delete unused callbacks or decrease panel size.");
}
}
else
{
}
thisCompute->mCurrentView.endGL();
_OPENMAYA_POP_WARNING
}
void
lensDistortionCompute::textureUpdate()
{
unsigned int width, height;
mPrimaryBuffer.getSize( width, height );
if ( mTextureWidth != width || mTextureHeight != height )
{
if ( mTextureIndex )
{
glDeleteTextures( 1, &mTextureIndex );
}
mTextureIndex = 0;
}
if (!mTextureIndex ){
glGenTextures( 1, &mTextureIndex );
glBindTexture( GL_TEXTURE_2D, mTextureIndex );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, MGL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, MGL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexImage2D(
GL_TEXTURE_2D
, 0
, GL_RGBA
, width
, height
, 0
, GL_RGBA
, GL_UNSIGNED_BYTE
, mPrimaryBuffer.pixels()
);
mTextureWidth = width;
mTextureHeight = height;
}
else
{
glBindTexture( GL_TEXTURE_2D, mTextureIndex );
glTexSubImage2D(
GL_TEXTURE_2D
, 0
, 0
, 0
, width
, height
, GL_RGBA
, GL_UNSIGNED_BYTE
, mPrimaryBuffer.pixels()
);
}
}
void
lensDistortionCompute::draw()
{
textureUpdate();
if (!mTextureIndex)
{
return;
}
mCurrentView.getCamera( camera );
double width = mCurrentView.portWidth();
double height = mCurrentView.portHeight();
int previewResolutionX = getIntValueFromCameraAttr( cameraNode,"previewResolutionX" );
int previewResolutionY = getIntValueFromCameraAttr( cameraNode,"previewResolutionY" );
double renderResolutionX = getDoubleValueFromCameraAttr( cameraNode,"renderResolutionX" );
double renderResolutionY = getDoubleValueFromCameraAttr( cameraNode,"renderResolutionY" );
double principalPointX = getDoubleValueFromCameraAttr( cameraNode,"principalPointX");
double principalPointY = getDoubleValueFromCameraAttr( cameraNode,"principalPointY" );
double kc1 = getDoubleValueFromCameraAttr( cameraNode,"radialDistortionCoef1" );
double kc2 = getDoubleValueFromCameraAttr( cameraNode,"radialDistortionCoef2" );
double kc3 = getDoubleValueFromCameraAttr( cameraNode,"tangentialDistortionCoef1" );
double kc4 = getDoubleValueFromCameraAttr( cameraNode,"tangentialDistortionCoef2" );
double horizontalFilmAperture = getDoubleValueFromCameraAttr( cameraNode,"horizontalFilmAperture" ) * 25.4;
double verticalFilmAperture = getDoubleValueFromCameraAttr( cameraNode,"verticalFilmAperture" ) * 25.4;
bool drawWireframe = getBoolValueFromCameraAttr( cameraNode, "drawWireframe" );
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
mCurrentView.beginGL();
_OPENMAYA_POP_WARNING
mCurrentView.projectionMatrix(projMatrix);
glPushMatrix();
glLoadMatrixd( (const GLdouble *)projMatrix.inverse().matrix );
glPushAttrib( GL_ALL_ATTRIB_BITS );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_TEXTURE_2D );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
if ( drawWireframe )
{
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( 0.95f, 1.0f );
}
drawLensDistortionPlane(
GL_QUADS
,renderResolutionX, renderResolutionY
,previewResolutionX, previewResolutionY
, width, height
, principalPointX, principalPointY
, kc1, kc2, kc3, kc4
, horizontalFilmAperture, verticalFilmAperture
);
glDisable( GL_TEXTURE_2D );
if ( drawWireframe )
{
glDisable( GL_POLYGON_OFFSET_FILL );
glColor3f( 0.0f, 0.0f, 0.0f );
drawLensDistortionPlane(
GL_LINE_LOOP
, renderResolutionX, renderResolutionY
, previewResolutionX, previewResolutionY
, width, height
, principalPointX, principalPointY
, kc1, kc2, kc3, kc4
, horizontalFilmAperture, verticalFilmAperture
);
}
glPopAttrib();
glPopMatrix();
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
mCurrentView.endGL();
_OPENMAYA_POP_WARNING
}
void
lensDistortionCompute::drawLensDistortionPlane(
GLenum drawMethod
, double renderResolutionX
, double renderResolutionY
, int previewResolutionX
, int previewResolutionY
, double width
, double height
, double principalPointX
, double principalPointY
, double kc1, double kc2, double kc3, double kc4
, double horizontalFilmAperture
, double verticalFilmAperture)
{
if ( previewResolutionX < 1 || previewResolutionY < 1 )
{
return;
}
double xSub = 1.0 / (double)previewResolutionX;
double ySub = 1.0 / (double)previewResolutionY;
for ( int i = 0; i < previewResolutionX ; i ++ )
{
for ( int j = 0; j < previewResolutionY; j++ )
{
glBegin( drawMethod );
double x, y;
double u, v;
x = u = i * xSub;
y = v = j * ySub;
applyLensDistortion(
x, y
,renderResolutionX, renderResolutionY
, width, height
, principalPointX, principalPointY
, kc1, kc2, kc3, kc4
, horizontalFilmAperture, verticalFilmAperture
);
glTexCoord2d( u, v );
glVertex2d( x, y );
x = u = i * xSub;
y = v = (j + 1) * ySub;
applyLensDistortion(
x, y
,renderResolutionX, renderResolutionY
, width, height
, principalPointX, principalPointY
, kc1, kc2, kc3, kc4
, horizontalFilmAperture, verticalFilmAperture
);
glTexCoord2d( u, v );
glVertex2d( x, y );
x = u = (i + 1) * xSub;
y = v = (j + 1) * ySub;
applyLensDistortion(
x, y
,renderResolutionX, renderResolutionY
, width, height
, principalPointX, principalPointY
, kc1, kc2, kc3, kc4
, horizontalFilmAperture, verticalFilmAperture
);
glTexCoord2d( u, v );
glVertex2d( x, y );
x = u = (i + 1) * xSub;
y = v = j * ySub;
applyLensDistortion(
x, y
,renderResolutionX, renderResolutionY
, width, height
, principalPointX, principalPointY
, kc1, kc2, kc3, kc4
, horizontalFilmAperture, verticalFilmAperture
);
glTexCoord2d( u, v );
glVertex2d( x, y );
glEnd();
}
}
}
void
lensDistortionCompute::applyLensDistortion(
double& Xd
, double& Yd
, double renderResolutionX
, double renderResolutionY
, double width
, double height
, double principalPointX
, double principalPointY
, double kc1, double kc2, double kc3, double kc4
, double horizontalFilmAperture
, double verticalFilmAperture
)
{
double Xn = Xd ;
double Yn = ( 1.0 - Yd ) ;
double centerOffsetX = principalPointX / renderResolutionX;
double centerOffsetY = principalPointY / renderResolutionY;
Xn = (Xn - centerOffsetX ) * (horizontalFilmAperture );
Yn = (Yn - centerOffsetY ) * (verticalFilmAperture) ;
if ( fabs( kc1 ) < kFloatEpsilon &&
fabs( kc2 ) < kFloatEpsilon &&
fabs( kc3 ) < kFloatEpsilon &&
fabs( kc4 ) < kFloatEpsilon
)
{
Xd = Xd * 2.0 - 1.0;
Yd = Yd * 2.0 - 1.0;
return;
}
double RR = (Xn * Xn) + (Yn * Yn);
double Q = 1 / ( (4 * kc1 * RR) + (6 * kc2 * RR*RR) + (8 * kc3 * Yn) + (8 * kc4 * Xn) + 1 );
Xd = Xn - Q * ( Xn * ( kc1 * RR + kc2 * RR * RR ) + 2 * kc3 * Xn * Yn + kc4 * ( RR + 2 * Xn * Xn) );
Yd = Yn - Q * ( Yn * ( kc1 * RR + kc2 * RR * RR ) +kc3 * ( RR + 2 * Yn * Yn) +2 * kc4 * Xn * Yn );
Xd = Xd / horizontalFilmAperture + centerOffsetX;
Yd = Yd / verticalFilmAperture + centerOffsetY ;
Yd = 1.0 - Yd;
Xd = Xd * 2.0 - 1.0;
Yd = Yd * 2.0 - 1.0;
}
int
lensDistortionCompute::getIntValueFromCameraAttr(
MObject& node,
MString attrName )
{
MPlug plug = nodeFn.findPlug( attrName, status );
if (status == MS::kSuccess )
{
}
else
{
}
return 0;
}
double
lensDistortionCompute::getDoubleValueFromCameraAttr(
MObject& node,
MString attrName )
{
MPlug plug = nodeFn.findPlug( attrName, status );
if (status == MS::kSuccess )
{
}
else
{
}
return 0.0;
}
bool
lensDistortionCompute::getBoolValueFromCameraAttr(
MObject& node,
MString attrName )
{
MPlug plug = nodeFn.findPlug( attrName, status );
if (status == MS::kSuccess )
{
}
else
{
}
return false;
}
{
MFnPlugin plugin( obj,
"Autodesk",
"1.0",
"Any");
for (unsigned int i=0; i<MAX_MODEL_PANEL; i++)
{
lensDistortionCompute::currentLensDistortionCompute[i] = 0;
}
status = plugin.registerCommand("lensDistortionCallback",
lensDistortionCallback::creator,
lensDistortionCallback::newSyntax);
if (!status)
{
}
return status;
}
{
for (unsigned int i=0; i<MAX_MODEL_PANEL; i++)
{
if ( lensDistortionCompute::currentLensDistortionCompute[i] )
{
delete lensDistortionCompute::currentLensDistortionCompute[i];
lensDistortionCompute::currentLensDistortionCompute[i] = 0;
}
}
status = plugin.deregisterCommand("lensDistortionCallback");
if (!status)
{
}
return status;
}