Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tcamera.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// TCamera
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCamera::TCamera()
Toshihiro Shimizu 890ddd
	: m_size(12, 9), m_res(768, 576), m_xPrevalence(true)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TCamera::setSize(const TDimensionD &size, bool preserveDpi, bool preserveAR)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double currAR = getAspectRatio();
Toshihiro Shimizu 890ddd
	TPointD currDpi = getDpi();
Toshihiro Shimizu 890ddd
	m_size.lx = size.lx;
Toshihiro Shimizu 890ddd
	if (preserveAR)
Toshihiro Shimizu 890ddd
		m_size.ly = m_size.lx / currAR; //WARNING! if also preserveDpi==true, the AR could lose precision...
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_size.ly = size.ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!preserveDpi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_res.lx = troundp(currDpi.x * m_size.lx);
Toshihiro Shimizu 890ddd
	m_res.ly = troundp(currDpi.y * m_size.ly);
Toshihiro Shimizu 890ddd
	m_size.lx = m_res.lx / currDpi.x;
Toshihiro Shimizu 890ddd
	if (preserveAR) //&& currDpi.x==currDpi.y)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		double aux = m_size.lx / currAR - m_res.ly / currDpi.y;
Toshihiro Shimizu 890ddd
		m_size.ly = m_size.lx / currAR;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		m_size.ly = m_res.ly / currDpi.y;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TCamera::getAspectRatio() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_size.lx / m_size.ly;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TCamera::setRes(const TDimension &res)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(res.lx > 0);
Toshihiro Shimizu 890ddd
	assert(res.ly > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_res != res) {
Toshihiro Shimizu 890ddd
		m_res = res;
Toshihiro Shimizu 890ddd
		m_interestRect = TRect();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPointD TCamera::getDpi() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD dpi;
Toshihiro Shimizu 890ddd
	if (m_size.lx > 0 && m_size.ly > 0) {
Toshihiro Shimizu 890ddd
		dpi.x = m_res.lx / m_size.lx;
Toshihiro Shimizu 890ddd
		dpi.y = m_res.ly / m_size.ly;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return dpi;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TCamera::isPixelSquared() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return areAlmostEqual(m_res.lx * m_size.ly, m_res.ly * m_size.lx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TAffine TCamera::getStageToCameraRef() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return TAffine(
Toshihiro Shimizu 890ddd
		m_res.lx / (Stage::inch * m_size.lx), 0, 0.5 * m_res.lx,
Toshihiro Shimizu 890ddd
		0, m_res.ly / (Stage::inch * m_size.ly), 0.5 * m_res.ly);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TAffine TCamera::getCameraToStageRef() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const double factor = Stage::inch;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TDimensionD cameraSize = getSize();
Toshihiro Shimizu 890ddd
	cameraSize.lx *= factor;
Toshihiro Shimizu 890ddd
	cameraSize.ly *= factor;
Toshihiro Shimizu 890ddd
	TPointD center(0.5 * cameraSize.lx, 0.5 * cameraSize.ly);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TAffine(
Toshihiro Shimizu 890ddd
		factor * m_size.lx / (double)m_res.lx, 0, -center.x,
Toshihiro Shimizu 890ddd
		0, factor * m_size.ly / (double)m_res.ly, -center.y);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD TCamera::getStageRect() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TDimensionD cameraSize = getSize();
Toshihiro Shimizu 890ddd
	const double factor = Stage::inch;
Toshihiro Shimizu 890ddd
	cameraSize.lx *= factor;
Toshihiro Shimizu 890ddd
	cameraSize.ly *= factor;
Toshihiro Shimizu 890ddd
	TRectD rect(cameraSize);
Toshihiro Shimizu 890ddd
	rect -= 0.5 * (rect.getP00() + rect.getP11());
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TCamera::setInterestRect(const TRect &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Not using the TRect's common intersection. Unfortunately, in case
Toshihiro Shimizu 890ddd
	//the rect's coordinates have lx or ly < 0, the intersection returns
Toshihiro Shimizu 890ddd
	//the default (empty) rect. We want to maintain the coordinates instead.
Toshihiro Shimizu 890ddd
	//m_interestRect = rect * TRect(m_res);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_interestRect.x0 = tmax(rect.x0, 0);
Toshihiro Shimizu 890ddd
	m_interestRect.y0 = tmax(rect.y0, 0);
Toshihiro Shimizu 890ddd
	m_interestRect.x1 = tmin(rect.x1, m_res.lx - 1);
Toshihiro Shimizu 890ddd
	m_interestRect.y1 = tmin(rect.y1, m_res.ly - 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD TCamera::getInterestStageRect() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return getCameraToStageRef() * TRectD(m_interestRect.x0, m_interestRect.y0, m_interestRect.x1 + 1, m_interestRect.y1 + 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TCamera::setInterestStageRect(const TRectD &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD cameraInterestRectD(
Toshihiro Shimizu 890ddd
		getStageToCameraRef() * rect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	setInterestRect(TRect(
Toshihiro Shimizu 890ddd
		tfloor(cameraInterestRectD.x0),
Toshihiro Shimizu 890ddd
		tfloor(cameraInterestRectD.y0),
Toshihiro Shimizu 890ddd
		tceil(cameraInterestRectD.x1) - 1,
Toshihiro Shimizu 890ddd
		tceil(cameraInterestRectD.y1) - 1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TCamera::saveData(TOStream &os) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	os.child("cameraSize") << m_size.lx << m_size.ly;
Toshihiro Shimizu 890ddd
	os.child("cameraRes") << m_res.lx << m_res.ly;
Toshihiro Shimizu 890ddd
	os.child("cameraXPrevalence") << (int)m_xPrevalence;
Toshihiro Shimizu 890ddd
	os.child("interestRect") << m_interestRect.x0 << m_interestRect.y0 << m_interestRect.x1 << m_interestRect.y1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TCamera::loadData(TIStream &is)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string tagName;
Toshihiro Shimizu 890ddd
	while (is.matchTag(tagName)) {
Toshihiro Shimizu 890ddd
		if (tagName == "cameraSize" || tagName == "size")
Toshihiro Shimizu 890ddd
			is >> m_size.lx >> m_size.ly;
Toshihiro Shimizu 890ddd
		else if (tagName == "cameraRes" || tagName == "res")
Toshihiro Shimizu 890ddd
			is >> m_res.lx >> m_res.ly;
Toshihiro Shimizu 890ddd
		else if (tagName == "cameraXPrevalence") {
Toshihiro Shimizu 890ddd
			int xPrevalence;
Toshihiro Shimizu 890ddd
			is >> xPrevalence;
Toshihiro Shimizu 890ddd
			m_xPrevalence = (bool)xPrevalence;
Toshihiro Shimizu 890ddd
		} else if (tagName == "interestRect") {
Toshihiro Shimizu 890ddd
			is >> m_interestRect.x0 >> m_interestRect.y0 >> m_interestRect.x1 >> m_interestRect.y1;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			throw TException("TCamera::loadData. unexpected tag: " + tagName);
Toshihiro Shimizu 890ddd
		is.matchEndTag();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}