#include "Turntable.h"
#include "TurntableDialog.h"
#include <QtCore/QFileInfo>
#include <QtGui/QImage>
#include <math.h>
MB_PLUGIN( "Turntable", "Create a turntable animation", "Autodesk", "http://www.mudbox3d.com", Turntable::Initializer );
int Turntable::s_iWidth = 0;
int Turntable::s_iHeight = 0;
int Turntable::s_iFrames = 120;
bool Turntable::s_bAntiAlias = false;
QString Turntable::s_sFolderPath;
void Turntable::Initializer()
{
Kernel()->AddCallbackMenuItem(Kernel::menuPlugins, QString::null, tr("Turntable Movie"), Turntable::CreateTurntable, NTRQ("Turntable Movie") );
}
void Turntable::CreateTurntable()
{
if (s_iWidth == 0) s_iWidth = Kernel()->ViewPort()->Width();
if (s_iHeight == 0) s_iHeight = Kernel()->ViewPort()->Height();
TurntableDialog* dlg = new TurntableDialog( NULL, s_iWidth, s_iHeight, s_iFrames, s_bAntiAlias, s_sFolderPath );
if ( dlg->exec() == QDialog::Accepted ) {
s_iWidth = dlg->Width();
s_iHeight = dlg->Height();
s_iFrames = dlg->Frames();
s_bAntiAlias = dlg->Antialias();
s_sFolderPath = dlg->FolderPath();
if ( s_iWidth < 50 ) s_iWidth = 50;
if ( s_iHeight < 50 ) s_iHeight = 50;
if ( s_iFrames < 1 ) s_iFrames = 1;
QFileInfo fi(s_sFolderPath);
if ( !fi.isDir() )
{
Kernel()->HUDMessageShow(tr("Turntable creation failed.<p>Specified folder does not exist."), Kernel::HUDmsgFade );
} else {
CreateTurntableImages(s_iWidth, s_iHeight, s_iFrames, s_bAntiAlias, s_sFolderPath);
}
}
delete dlg;
}
static Vector rotateAroundYAxis( const Vector& start, float theta )
{
float cx = start.x;
float cy = start.z;
float cosTheta = cos(theta);
float sinTheta = sin(theta);
float rx = cx * cosTheta + cy * sinTheta;
float ry = cy * cosTheta - cx * sinTheta;
return Vector(rx,start.y,ry);
}
void Turntable::CreateTurntableImages( int width, int height, int numberOfFrames, bool antialias, const QString& folderPath )
{
mudbox::Camera* camera = Kernel()->Scene()->ActiveCamera();
const float twoPi = 2.0 * 3.1415926535;
float step = ( twoPi / float(numberOfFrames) );
Vector cameraForward( camera->Forward() );
Vector cameraUp( camera->Up() );
Vector cameraRight( camera->Right() );
Vector position( camera->Position() );
float flatDistanceToCenter = sqrt( position.x * position.x + position.z * position.z );
float flatSizeOfForward = sqrt( cameraForward.x * cameraForward.x + cameraForward.z * cameraForward.z );
float heightAtCenter = 0.0;
if ( flatSizeOfForward > 0.0 )
{
heightAtCenter = position.y - (flatDistanceToCenter/flatSizeOfForward) * cameraForward.y;
camera->SetTarget(Vector(0.0f, heightAtCenter, 0.0f));
}
Kernel()->ProgressStart(QString(tr("Saving frames...")), numberOfFrames );
bool finishedOk = true;
for ( int i=0; i < numberOfFrames; i++ )
{
if ( Kernel()->ProgressIsCancelRequested() ) {
finishedOk = false;
break;
}
Kernel()->ProgressAdd();
Image* frame = Kernel()->RenderScene( width * (antialias?4:1), height * (antialias?4:1) );
QString fileName = QString("%1/frame_%2.png").arg(folderPath).arg(i);
QImage *sampleQImage = frame->ConvertToQImage();
(*sampleQImage) = sampleQImage->convertToFormat(QImage::Format_RGB888);
delete frame;
if ( antialias )
{
(*sampleQImage) = sampleQImage->scaled(width,height,Qt::KeepAspectRatio,Qt::SmoothTransformation);
}
sampleQImage->save(fileName, "png");
delete sampleQImage;
float Theta = step * float(i+1);
Vector newPosition( rotateAroundYAxis(position,Theta) );
camera->SetPosition( newPosition);
newPosition = camera->Position();
camera->SetTarget(Vector(0.0f, heightAtCenter, 0.0f));
}
Kernel()->ProgressEnd();
camera->SetPosition( position );
camera->SetForwardUpRight(cameraForward, cameraUp, cameraRight);
if ( finishedOk )
{
Kernel()->HUDMessageShow(tr("Turntable is complete"), Kernel::HUDmsgFade );
} else {
Kernel()->HUDMessageShow(tr("Turntable creation cancelled"), Kernel::HUDmsgFade );
}
}