<commit_before>#include "VDTexture.h"

#include "cinder/gl/Texture.h"
#include "cinder/Xml.h"

using namespace ci;
using namespace ci::app;

namespace VideoDromm {
	VDTexture::VDTexture(TextureType aType)
		: mFilePathOrText("")
		, mName("")
		, mTopDown(true)
		, mFlipV(false)
		, mFlipH(true)
		, mWidth(640)
		, mHeight(480)
	{

		if (mName.length() == 0) {
			mName = mFilePathOrText;
		}
		// init the texture whatever happens next
		if (mFilePathOrText.length() > 0) {
			mTexture = ci::gl::Texture::create(ci::loadImage(mFilePathOrText), ci::gl::Texture::Format().loadTopDown(mTopDown));
		}
		else {
			mTexture = ci::gl::Texture::create(mWidth, mHeight, ci::gl::Texture::Format().loadTopDown(mTopDown));
		}
	}
	VDTexture::~VDTexture(void) {

	}

	VDTextureList VDTexture::readSettings(const DataSourceRef &source)
	{
		XmlTree			doc;
		VDTextureList	vdtexturelist;

		// try to load the specified xml file
		try { doc = XmlTree(source); }
		catch (...) { return vdtexturelist; }

		// check if this is a valid file
		bool isOK = doc.hasChild("textures");
		if (!isOK) return vdtexturelist;

		//
		if (isOK) {

			XmlTree texturesXml = doc.getChild("textures");

			// iterate textures
			for (XmlTree::ConstIter child = texturesXml.begin("texture"); child != texturesXml.end(); ++child) {
				// create texture of the correct type
				std::string texturetype = child->getAttributeValue<std::string>("texturetype", "unknown");
				XmlTree detailsXml = child->getChild("details");

				//std::string filepath = detailsXml.getAttributeValue<std::string>("filepath", "");
				if (texturetype == "image") {
					TextureImageRef t(new TextureImage());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
				else if (texturetype == "text") {
					TextureTextRef t(new TextureText());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
				else if (texturetype == "movie") {
					TextureMovieRef t(new TextureMovie());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
				else if (texturetype == "camera") {
					TextureCameraRef t(new TextureCamera());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
			}
		}

		return vdtexturelist;
	}

	void VDTexture::writeSettings(const VDTextureList &vdtexturelist, const ci::DataTargetRef &target) {

		// create config document and root <textures>
		XmlTree			doc;
		doc.setTag("textures");
		doc.setAttribute("version", "1.0");

		//
		for (unsigned i = 0; i < vdtexturelist.size(); ++i) {
			// create <texture>
			XmlTree			texture;
			texture.setTag("texture");
			texture.setAttribute("id", i + 1);
			switch (vdtexturelist[i]->mType) {
			case IMAGE: texture.setAttribute("texturetype", "image"); break;
			case TEXT: texture.setAttribute("texturetype", "text"); break;
			case MOVIE: texture.setAttribute("texturetype", "movie"); break;
			case CAMERA: texture.setAttribute("texturetype", "camera"); break;
			default: texture.setAttribute("texturetype", "unknown"); break;
			}
			// details specific to texture type
			texture.push_back(vdtexturelist[i]->toXml());

			// add texture doc
			//texture.setAttribute("filepath", vdtexturelist[i]->mFilePathOrText);
			doc.push_back(texture);
		}

		// write file
		doc.write(target);
	}
	XmlTree	VDTexture::toXml() const
	{
		XmlTree		xml;
		xml.setTag("details");
		xml.setAttribute("filepath", mFilePathOrText);
		xml.setAttribute("width", mWidth);
		xml.setAttribute("height", mHeight);

		return xml;
	}

	void VDTexture::fromXml(const XmlTree &xml)
	{

	}

	int VDTexture::getTextureWidth() {
		return mWidth;
	};

	int VDTexture::getTextureHeight() {
		return mHeight;
	};

	ci::ivec2 VDTexture::getSize() {
		return mTexture->getSize();
	}

	ci::Area VDTexture::getBounds() {
		return mTexture->getBounds();
	}

	GLuint VDTexture::getId() {
		return mTexture->getId();
	}

	std::string VDTexture::getName(){
		return mName;
	}

	ci::gl::TextureRef VDTexture::getTexture() {
		return mTexture;
	}
	// --------- child classes
	TextureImage::TextureImage() {
	}
	XmlTree	TextureImage::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("path", getAssetPath("").string());
		xml.setAttribute("topdown", mTopDown);
		return xml;
	}

	void TextureImage::fromXml(const XmlTree &xml)
	{
		VDTexture::fromXml(xml);
		mType = IMAGE;
		// retrieve attributes specific to this type of texture
		mTopDown = xml.getAttributeValue<bool>("topdown", "false");
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		if (mFilePathOrText.length() > 0) {
			fs::path fullPath = getAssetPath("") / mFilePathOrText;// TODO / mVDSettings->mAssetsPath
			if (fs::exists(fullPath)) {
				// TODO mTopDown has no effect!?!
				mTexture = ci::gl::Texture::create(loadImage(loadAsset(mFilePathOrText)), ci::gl::Texture::Format().loadTopDown(mTopDown));
			}
			else {
				mTexture = ci::gl::Texture::create(mWidth, mHeight, ci::gl::Texture::Format().loadTopDown(mTopDown));
			}
		}
	}
	ci::gl::Texture2dRef TextureImage::getTexture() {
		return mTexture;
	}
	TextureImage::~TextureImage(void) {

	}
	// TextureText
	TextureText::TextureText() {
		// font
		Font customFont(Font(loadAsset("Signika-Regular.ttf"), 100));
		gl::TextureFont::Format f;
		f.enableMipmapping(true);
		mTextureFont = gl::TextureFont::create(customFont, f);

		// camera
		mCamDist = 600.0f;
		mCam.setPerspective(75.0f, getWindowAspectRatio(), 0.1f, 15000.0f);
		mCam.lookAt(vec3(0.0f, 0.0f, mCamDist), vec3(0), vec3(0, 1, 0));
		mCam.setLensShiftHorizontal(-0.6);
		// scene
		mSceneMatrix = mSceneDestMatrix = mat4(1.0f); // identity

		// init text
		addChar('Y'); addChar('O');
		stringIndex = 0;

		currentFrame = -1;
		startFrame = 0;
		// fbo
		gl::Fbo::Format format;
		//format.setSamples( 4 ); // uncomment this to enable 4x antialiasing
		mFbo = gl::Fbo::create(mWidth, mHeight, format.depthTexture());
	}
	void TextureText::fromXml(const XmlTree &xml)
	{
		mType = TEXT;
		// retrieve attributes specific to this type of texture
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		if (mFilePathOrText.length() > 0) {
			fs::path fullPath = getAssetPath("") / mFilePathOrText;// TODO / mVDSettings->mAssetsPath
			if (fs::exists(fullPath)) {

				try {
					mText = JsonTree(app::loadAsset(mFilePathOrText));// TODO / mVDSettings->mAssetsPath
					mStrings.clear();

					for (const auto &line : mText["lines"]) {
						mStrings.push_back(line.getValue());
					}

					CI_LOG_V("successfully loaded " + mFilePathOrText);
				}
				catch (Exception &exc) {
					CI_LOG_EXCEPTION("error loading ", exc);
				}
			}
		}
	}
	XmlTree	TextureText::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("filepath", mFilePathOrText);
		return xml;
	}
	ci::gl::Texture2dRef TextureText::getTexture() {
#if defined( CINDER_MSW )
		// should be in update?
		//addChar('O');

		if (frame < mStrings[stringIndex].size() - 1) {
			char c[2];
			printf_s(c, "%s", mStrings[stringIndex].substr(frame, 1).c_str());
			addChar(*c);
		}
		gl::ScopedFramebuffer fbScp(mFbo);
		gl::clear(Color::black());
		// setup the viewport to match the dimensions of the FBO
		gl::ScopedViewport scpVp(ivec2(0), mFbo->getSize());
		for (vector<Character>::iterator it = mCharacters.begin(); it != mCharacters.end(); ++it)
			it->draw();

		for (list<Character>::iterator it = mDyingCharacters.begin(); it != mDyingCharacters.end(); ++it)
			it->draw();

		if ((!mDyingCharacters.empty()) && mDyingCharacters.front().isDead())
			mDyingCharacters.pop_front();
		return mFbo->getColorTexture();
#else
		return mTexture;
#endif
	}
#if defined( CINDER_MSW )
	void TextureText::addChar(char c)
	{
		if (c == 32) {
			c = 97;
		}
		else {
			c = toupper(c);
		}
		int count = mCharacters.size();

		if (count > 0)
			mSceneDestMatrix = glm::translate(mSceneDestMatrix, vec3(mCharacters.back().getKernBounds().getWidth() / 2.0f, 0.0f, 0.0f));

		glm::mat4 randStartMatrix = mSceneDestMatrix;
		randStartMatrix = glm::translate(randStartMatrix, vec3(300.0f));

		mCharacters.push_back(Character(mTextureFont, string(&c, 1), randStartMatrix));

		//mSceneDestMatrix.translate(vec3(mCharacters.back().getKernBounds().getWidth() / 2.0f, 0.0f, 0.0f));
		mSceneDestMatrix = glm::translate(mSceneDestMatrix, vec3(mCharacters.back().getKernBounds().getWidth() / 2.0f, 0.0f, 0.0f));

		float t = (count + 281) / 50.0f;
		//mSceneDestMatrix.rotate(Vec3f(sin(t)*0.1f, cos(t)*0.2f, cos(t)*0.05f)); // makes the scene meander

		mCharacters.back().animIn(timeline(), mSceneDestMatrix);

		timeline().apply(&mSceneMatrix, mSceneDestMatrix, 1.0f, EaseOutAtan(10));

	}

	void TextureText::removeChar()
	{
		if (!mCharacters.empty()) {
			mDyingCharacters.push_back(mCharacters.back());
			mCharacters.pop_back();

			if (!mCharacters.empty())
				mSceneDestMatrix = mCharacters.back().getDestMatrix();
			else
				mSceneDestMatrix = mat4(1.0f);

			mat4 randStartMatrix = glm::translate( mSceneDestMatrix, vec3(300.0f));
			//randStartMatrix.translate(300.0f);

			//randStartMatrix.rotate(getRandomVec3f(2.0f, 6.0f));

			mDyingCharacters.back().animOut(timeline(), randStartMatrix);

			timeline().apply(&mSceneMatrix, mSceneDestMatrix, 1.0f, EaseOutAtan(10));
		}
	}
#else

#endif
	TextureText::~TextureText(void) {

	}

	// TextureMovie
	TextureMovie::TextureMovie() {

	}
	void TextureMovie::fromXml(const XmlTree &xml)
	{
		// retrieve attributes specific to this type of texture
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		mType = MOVIE;

	}
	XmlTree	TextureMovie::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("filepath", mFilePathOrText);
		return xml;
	}
	ci::gl::Texture2dRef TextureMovie::getTexture() {
		return mTexture;
	}
	TextureMovie::~TextureMovie(void) {

	}

	// TextureCamera
#if (defined(  CINDER_MSW) ) || (defined( CINDER_MAC ))
	TextureCamera::TextureCamera() {
		mFirstCameraDeviceName = "";
		printDevices();

		try {
			mCapture = Capture::create(640, 480);
			mCapture->start();
		}
		catch (ci::Exception &exc) {
			CI_LOG_EXCEPTION("Failed to init capture ", exc);
		}
	}
	void TextureCamera::fromXml(const XmlTree &xml)
	{
		// retrieve attributes specific to this type of texture
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		mType = CAMERA;

	}
	XmlTree	TextureCamera::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("camera", mFirstCameraDeviceName);
		return xml;
	}
	ci::gl::Texture2dRef TextureCamera::getTexture() {
		if (mCapture && mCapture->checkNewFrame()) {
			if (!mTexture) {
				// Capture images come back as top-down, and it's more efficient to keep them that way
				mTexture = gl::Texture::create(*mCapture->getSurface(), gl::Texture::Format().loadTopDown());
			}
			else {
				mTexture->update(*mCapture->getSurface());
			}
		}
		return mTexture;
	}
	void TextureCamera::printDevices()
	{
		for (const auto &device : Capture::getDevices()) {
			console() << "Device: " << device->getName() << " "
#if defined( CINDER_COCOA_TOUCH )
				<< (device->isFrontFacing() ? "Front" : "Rear") << "-facing"
#endif
				<< endl;
			mFirstCameraDeviceName = device->getName();
		}
	}
	TextureCamera::~TextureCamera(void) {

	}
#else

#endif
} // namespace VideoDromm
<commit_msg>mac fix<commit_after>#include "VDTexture.h"

#include "cinder/gl/Texture.h"
#include "cinder/Xml.h"

using namespace ci;
using namespace ci::app;

namespace VideoDromm {
	VDTexture::VDTexture(TextureType aType)
		: mFilePathOrText("")
		, mName("")
		, mTopDown(true)
		, mFlipV(false)
		, mFlipH(true)
		, mWidth(640)
		, mHeight(480)
	{

		if (mName.length() == 0) {
			mName = mFilePathOrText;
		}
		// init the texture whatever happens next
		if (mFilePathOrText.length() > 0) {
			mTexture = ci::gl::Texture::create(ci::loadImage(mFilePathOrText), ci::gl::Texture::Format().loadTopDown(mTopDown));
		}
		else {
			mTexture = ci::gl::Texture::create(mWidth, mHeight, ci::gl::Texture::Format().loadTopDown(mTopDown));
		}
	}
	VDTexture::~VDTexture(void) {

	}

	VDTextureList VDTexture::readSettings(const DataSourceRef &source)
	{
		XmlTree			doc;
		VDTextureList	vdtexturelist;

		// try to load the specified xml file
		try { doc = XmlTree(source); }
		catch (...) { return vdtexturelist; }

		// check if this is a valid file
		bool isOK = doc.hasChild("textures");
		if (!isOK) return vdtexturelist;

		//
		if (isOK) {

			XmlTree texturesXml = doc.getChild("textures");

			// iterate textures
			for (XmlTree::ConstIter child = texturesXml.begin("texture"); child != texturesXml.end(); ++child) {
				// create texture of the correct type
				std::string texturetype = child->getAttributeValue<std::string>("texturetype", "unknown");
				XmlTree detailsXml = child->getChild("details");

				//std::string filepath = detailsXml.getAttributeValue<std::string>("filepath", "");
				if (texturetype == "image") {
					TextureImageRef t(new TextureImage());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
				else if (texturetype == "text") {
					TextureTextRef t(new TextureText());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
				else if (texturetype == "movie") {
					TextureMovieRef t(new TextureMovie());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
				else if (texturetype == "camera") {
					TextureCameraRef t(new TextureCamera());
					t->fromXml(detailsXml);
					vdtexturelist.push_back(t);
				}
			}
		}

		return vdtexturelist;
	}

	void VDTexture::writeSettings(const VDTextureList &vdtexturelist, const ci::DataTargetRef &target) {

		// create config document and root <textures>
		XmlTree			doc;
		doc.setTag("textures");
		doc.setAttribute("version", "1.0");

		//
		for (unsigned i = 0; i < vdtexturelist.size(); ++i) {
			// create <texture>
			XmlTree			texture;
			texture.setTag("texture");
			texture.setAttribute("id", i + 1);
			switch (vdtexturelist[i]->mType) {
			case IMAGE: texture.setAttribute("texturetype", "image"); break;
			case TEXT: texture.setAttribute("texturetype", "text"); break;
			case MOVIE: texture.setAttribute("texturetype", "movie"); break;
			case CAMERA: texture.setAttribute("texturetype", "camera"); break;
			default: texture.setAttribute("texturetype", "unknown"); break;
			}
			// details specific to texture type
			texture.push_back(vdtexturelist[i]->toXml());

			// add texture doc
			//texture.setAttribute("filepath", vdtexturelist[i]->mFilePathOrText);
			doc.push_back(texture);
		}

		// write file
		doc.write(target);
	}
	XmlTree	VDTexture::toXml() const
	{
		XmlTree		xml;
		xml.setTag("details");
		xml.setAttribute("filepath", mFilePathOrText);
		xml.setAttribute("width", mWidth);
		xml.setAttribute("height", mHeight);

		return xml;
	}

	void VDTexture::fromXml(const XmlTree &xml)
	{

	}

	int VDTexture::getTextureWidth() {
		return mWidth;
	};

	int VDTexture::getTextureHeight() {
		return mHeight;
	};

	ci::ivec2 VDTexture::getSize() {
		return mTexture->getSize();
	}

	ci::Area VDTexture::getBounds() {
		return mTexture->getBounds();
	}

	GLuint VDTexture::getId() {
		return mTexture->getId();
	}

	std::string VDTexture::getName(){
		return mName;
	}

	ci::gl::TextureRef VDTexture::getTexture() {
		return mTexture;
	}
	// --------- child classes
	TextureImage::TextureImage() {
	}
	XmlTree	TextureImage::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("path", getAssetPath("").string());
		xml.setAttribute("topdown", mTopDown);
		return xml;
	}

	void TextureImage::fromXml(const XmlTree &xml)
	{
		VDTexture::fromXml(xml);
		mType = IMAGE;
		// retrieve attributes specific to this type of texture
		mTopDown = xml.getAttributeValue<bool>("topdown", "false");
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		if (mFilePathOrText.length() > 0) {
			fs::path fullPath = getAssetPath("") / mFilePathOrText;// TODO / mVDSettings->mAssetsPath
			if (fs::exists(fullPath)) {
				// TODO mTopDown has no effect!?!
				mTexture = ci::gl::Texture::create(loadImage(loadAsset(mFilePathOrText)), ci::gl::Texture::Format().loadTopDown(mTopDown));
			}
			else {
				mTexture = ci::gl::Texture::create(mWidth, mHeight, ci::gl::Texture::Format().loadTopDown(mTopDown));
			}
		}
	}
	ci::gl::Texture2dRef TextureImage::getTexture() {
		return mTexture;
	}
	TextureImage::~TextureImage(void) {

	}
	// TextureText
	TextureText::TextureText() {
		// font
		Font customFont(Font(loadAsset("Signika-Regular.ttf"), 100));
		gl::TextureFont::Format f;
		f.enableMipmapping(true);
		mTextureFont = gl::TextureFont::create(customFont, f);

		// camera
		mCamDist = 600.0f;
		mCam.setPerspective(75.0f, getWindowAspectRatio(), 0.1f, 15000.0f);
		mCam.lookAt(vec3(0.0f, 0.0f, mCamDist), vec3(0), vec3(0, 1, 0));
		mCam.setLensShiftHorizontal(-0.6);
		// scene
		mSceneMatrix = mSceneDestMatrix = mat4(1.0f); // identity

		// init text
#if defined( CINDER_MSW )
		addChar('Y'); addChar('O');
#endif
		stringIndex = 0;

		currentFrame = -1;
		startFrame = 0;
		// fbo
		gl::Fbo::Format format;
		//format.setSamples( 4 ); // uncomment this to enable 4x antialiasing
		mFbo = gl::Fbo::create(mWidth, mHeight, format.depthTexture());
	}
	void TextureText::fromXml(const XmlTree &xml)
	{
		mType = TEXT;
		// retrieve attributes specific to this type of texture
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		if (mFilePathOrText.length() > 0) {
			fs::path fullPath = getAssetPath("") / mFilePathOrText;// TODO / mVDSettings->mAssetsPath
			if (fs::exists(fullPath)) {

				try {
					mText = JsonTree(app::loadAsset(mFilePathOrText));// TODO / mVDSettings->mAssetsPath
					mStrings.clear();

					for (const auto &line : mText["lines"]) {
						mStrings.push_back(line.getValue());
					}

					CI_LOG_V("successfully loaded " + mFilePathOrText);
				}
				catch (Exception &exc) {
					CI_LOG_EXCEPTION("error loading ", exc);
				}
			}
		}
	}
	XmlTree	TextureText::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("filepath", mFilePathOrText);
		return xml;
	}
	ci::gl::Texture2dRef TextureText::getTexture() {
#if defined( CINDER_MSW )
		// should be in update?
		//addChar('O');

		if (frame < mStrings[stringIndex].size() - 1) {
			char c[2];
			printf_s(c, "%s", mStrings[stringIndex].substr(frame, 1).c_str());
			addChar(*c);
		}
		gl::ScopedFramebuffer fbScp(mFbo);
		gl::clear(Color::black());
		// setup the viewport to match the dimensions of the FBO
		gl::ScopedViewport scpVp(ivec2(0), mFbo->getSize());
		for (vector<Character>::iterator it = mCharacters.begin(); it != mCharacters.end(); ++it)
			it->draw();

		for (list<Character>::iterator it = mDyingCharacters.begin(); it != mDyingCharacters.end(); ++it)
			it->draw();

		if ((!mDyingCharacters.empty()) && mDyingCharacters.front().isDead())
			mDyingCharacters.pop_front();
		return mFbo->getColorTexture();
#else
		return mTexture;
#endif
	}
#if defined( CINDER_MSW )
	void TextureText::addChar(char c)
	{
		if (c == 32) {
			c = 97;
		}
		else {
			c = toupper(c);
		}
		int count = mCharacters.size();

		if (count > 0)
			mSceneDestMatrix = glm::translate(mSceneDestMatrix, vec3(mCharacters.back().getKernBounds().getWidth() / 2.0f, 0.0f, 0.0f));

		glm::mat4 randStartMatrix = mSceneDestMatrix;
		randStartMatrix = glm::translate(randStartMatrix, vec3(300.0f));

		mCharacters.push_back(Character(mTextureFont, string(&c, 1), randStartMatrix));

		//mSceneDestMatrix.translate(vec3(mCharacters.back().getKernBounds().getWidth() / 2.0f, 0.0f, 0.0f));
		mSceneDestMatrix = glm::translate(mSceneDestMatrix, vec3(mCharacters.back().getKernBounds().getWidth() / 2.0f, 0.0f, 0.0f));

		float t = (count + 281) / 50.0f;
		//mSceneDestMatrix.rotate(Vec3f(sin(t)*0.1f, cos(t)*0.2f, cos(t)*0.05f)); // makes the scene meander

		mCharacters.back().animIn(timeline(), mSceneDestMatrix);

		timeline().apply(&mSceneMatrix, mSceneDestMatrix, 1.0f, EaseOutAtan(10));

	}

	void TextureText::removeChar()
	{
		if (!mCharacters.empty()) {
			mDyingCharacters.push_back(mCharacters.back());
			mCharacters.pop_back();

			if (!mCharacters.empty())
				mSceneDestMatrix = mCharacters.back().getDestMatrix();
			else
				mSceneDestMatrix = mat4(1.0f);

			mat4 randStartMatrix = glm::translate( mSceneDestMatrix, vec3(300.0f));
			//randStartMatrix.translate(300.0f);

			//randStartMatrix.rotate(getRandomVec3f(2.0f, 6.0f));

			mDyingCharacters.back().animOut(timeline(), randStartMatrix);

			timeline().apply(&mSceneMatrix, mSceneDestMatrix, 1.0f, EaseOutAtan(10));
		}
	}
#else

#endif
	TextureText::~TextureText(void) {

	}

	// TextureMovie
	TextureMovie::TextureMovie() {

	}
	void TextureMovie::fromXml(const XmlTree &xml)
	{
		// retrieve attributes specific to this type of texture
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		mType = MOVIE;

	}
	XmlTree	TextureMovie::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("filepath", mFilePathOrText);
		return xml;
	}
	ci::gl::Texture2dRef TextureMovie::getTexture() {
		return mTexture;
	}
	TextureMovie::~TextureMovie(void) {

	}

	// TextureCamera
#if (defined(  CINDER_MSW) ) || (defined( CINDER_MAC ))
	TextureCamera::TextureCamera() {
		mFirstCameraDeviceName = "";
		printDevices();

		try {
			mCapture = Capture::create(640, 480);
			mCapture->start();
		}
		catch (ci::Exception &exc) {
			CI_LOG_EXCEPTION("Failed to init capture ", exc);
		}
	}
	void TextureCamera::fromXml(const XmlTree &xml)
	{
		// retrieve attributes specific to this type of texture
		mFilePathOrText = xml.getAttributeValue<string>("filepath", "");
		mType = CAMERA;

	}
	XmlTree	TextureCamera::toXml() const {
		XmlTree xml = VDTexture::toXml();

		// add attributes specific to this type of texture
		xml.setAttribute("camera", mFirstCameraDeviceName);
		return xml;
	}
	ci::gl::Texture2dRef TextureCamera::getTexture() {
		if (mCapture && mCapture->checkNewFrame()) {
			if (!mTexture) {
				// Capture images come back as top-down, and it's more efficient to keep them that way
				mTexture = gl::Texture::create(*mCapture->getSurface(), gl::Texture::Format().loadTopDown());
			}
			else {
				mTexture->update(*mCapture->getSurface());
			}
		}
		return mTexture;
	}
	void TextureCamera::printDevices()
	{
		for (const auto &device : Capture::getDevices()) {
			console() << "Device: " << device->getName() << " "
#if defined( CINDER_COCOA_TOUCH )
				<< (device->isFrontFacing() ? "Front" : "Rear") << "-facing"
#endif
				<< endl;
			mFirstCameraDeviceName = device->getName();
		}
	}
	TextureCamera::~TextureCamera(void) {

	}
#else

#endif
} // namespace VideoDromm
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file ViewStyle.cxx
 ** Store information on how the document is to be viewed.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"

MarginStyle::MarginStyle() :
	symbol(false), width(16), mask(0xffffffff), sensitive(false) {
}

// A list of the fontnames - avoids wasting space in each style
FontNames::FontNames() {
	max = 0;
}

FontNames::~FontNames() {
	Clear();
}

void FontNames::Clear() {
	for (int i=0;i<max;i++) {
		delete []names[i];
	}
	max = 0;
}

const char *FontNames::Save(const char *name) {
	if (!name)
		return 0;
	for (int i=0;i<max;i++) {
		if (strcmp(names[i], name) == 0) {
			return names[i];
		}
	}
	names[max] = new char[strlen(name) + 1];
	strcpy(names[max], name);
	max++;
	return names[max-1];
}

ViewStyle::ViewStyle() {
	Init();
}

ViewStyle::ViewStyle(const ViewStyle &source) {
	Init();
	for (unsigned int sty=0;sty<(sizeof(styles)/sizeof(styles[0]));sty++) {
		styles[sty] = source.styles[sty];
		// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
		styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
	}
	for (int mrk=0;mrk<=MARKER_MAX;mrk++) {
		markers[mrk] = source.markers[mrk];
	}
	for (int ind=0;ind<=INDIC_MAX;ind++) {
		indicators[ind] = source.indicators[ind];
	}

	selforeset = source.selforeset;
	selforeground.desired = source.selforeground.desired;
	selbackset = source.selbackset;
	selbackground.desired = source.selbackground.desired;
	selbackground2.desired = source.selbackground2.desired;

	foldmarginColourSet = source.foldmarginColourSet;
	foldmarginColour.desired = source.foldmarginColour.desired;
	foldmarginHighlightColourSet = source.foldmarginHighlightColourSet;
	foldmarginHighlightColour.desired = source.foldmarginHighlightColour.desired;

	hotspotForegroundSet = source.hotspotForegroundSet;
	hotspotForeground.desired = source.hotspotForeground.desired;
	hotspotBackgroundSet = source.hotspotBackgroundSet;
	hotspotBackground.desired = source.hotspotBackground.desired;
	hotspotUnderline = source.hotspotUnderline;
	hotspotSingleLine = source.hotspotSingleLine;

	whitespaceForegroundSet = source.whitespaceForegroundSet;
	whitespaceForeground.desired = source.whitespaceForeground.desired;
	whitespaceBackgroundSet = source.whitespaceBackgroundSet;
	whitespaceBackground.desired = source.whitespaceBackground.desired;
	selbar.desired = source.selbar.desired;
	selbarlight.desired = source.selbarlight.desired;
	caretcolour.desired = source.caretcolour.desired;
	showCaretLineBackground = source.showCaretLineBackground;
	caretLineBackground.desired = source.caretLineBackground.desired;
	edgecolour.desired = source.edgecolour.desired;
	edgeState = source.edgeState;
	caretWidth = source.caretWidth;
	leftMarginWidth = source.leftMarginWidth;
	rightMarginWidth = source.rightMarginWidth;
	for (int i=0;i < margins; i++) {
		ms[i] = source.ms[i];
	}
	symbolMargin = source.symbolMargin;
	maskInLine = source.maskInLine;
	fixedColumnWidth = source.fixedColumnWidth;
	zoomLevel = source.zoomLevel;
	viewWhitespace = source.viewWhitespace;
	viewIndentationGuides = source.viewIndentationGuides;
	viewEOL = source.viewEOL;
	showMarkedLines = source.showMarkedLines;
}

ViewStyle::~ViewStyle() {
}

void ViewStyle::Init() {
	fontNames.Clear();
	ResetDefaultStyle();

	indicators[0].style = INDIC_SQUIGGLE;
	indicators[0].fore = ColourDesired(0, 0x7f, 0);
	indicators[1].style = INDIC_TT;
	indicators[1].fore = ColourDesired(0, 0, 0xff);
	indicators[2].style = INDIC_PLAIN;
	indicators[2].fore = ColourDesired(0xff, 0, 0);

	lineHeight = 1;
	maxAscent = 1;
	maxDescent = 1;
	aveCharWidth = 8;
	spaceWidth = 8;

	selforeset = false;
	selforeground.desired = ColourDesired(0xff, 0, 0);
	selbackset = true;
	selbackground.desired = ColourDesired(0xc0, 0xc0, 0xc0);
	selbackground2.desired = ColourDesired(0xb0, 0xb0, 0xb0);

	foldmarginColourSet = false;
	foldmarginColour.desired = ColourDesired(0xff, 0, 0);
	foldmarginHighlightColourSet = false;
	foldmarginHighlightColour.desired = ColourDesired(0xc0, 0xc0, 0xc0);

	whitespaceForegroundSet = false;
	whitespaceForeground.desired = ColourDesired(0, 0, 0);
	whitespaceBackgroundSet = false;
	whitespaceBackground.desired = ColourDesired(0xff, 0xff, 0xff);
	selbar.desired = Platform::Chrome();
	selbarlight.desired = Platform::ChromeHighlight();
	styles[STYLE_LINENUMBER].fore.desired = ColourDesired(0, 0, 0);
	styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
	caretcolour.desired = ColourDesired(0, 0, 0);
	showCaretLineBackground = false;
	caretLineBackground.desired = ColourDesired(0xff, 0xff, 0);
	edgecolour.desired = ColourDesired(0xc0, 0xc0, 0xc0);
	edgeState = EDGE_NONE;
	caretWidth = 1;
	someStylesProtected = false;

	hotspotForegroundSet = false;
	hotspotForeground.desired = ColourDesired(0, 0, 0xff);
	hotspotBackgroundSet = false;
	hotspotBackground.desired = ColourDesired(0xff, 0xff, 0xff);
	hotspotUnderline = true;
	hotspotSingleLine = true;

	leftMarginWidth = 1;
	rightMarginWidth = 1;
	ms[0].symbol = false;
	ms[0].width = 0;
	ms[0].mask = 0;
	ms[1].symbol = true;
	ms[1].width = 16;
	ms[1].mask = ~SC_MASK_FOLDERS;
	ms[2].symbol = true;
	ms[2].width = 0;
	ms[2].mask = 0;
	fixedColumnWidth = leftMarginWidth;
	symbolMargin = false;
	maskInLine = 0xffffffff;
	for (int margin=0; margin < margins; margin++) {
		fixedColumnWidth += ms[margin].width;
		symbolMargin = symbolMargin || ms[margin].symbol;
		if (ms[margin].width > 0)
			maskInLine &= ~ms[margin].mask;
	}
	zoomLevel = 0;
	viewWhitespace = wsInvisible;
	viewIndentationGuides = false;
	viewEOL = false;
	showMarkedLines = true;
}

void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
	unsigned int i;
	for (i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
		pal.WantFind(styles[i].fore, want);
		pal.WantFind(styles[i].back, want);
	}
	for (i=0;i<(sizeof(indicators)/sizeof(indicators[0]));i++) {
		pal.WantFind(indicators[i].fore, want);
	}
	for (i=0;i<(sizeof(markers)/sizeof(markers[0]));i++) {
		markers[i].RefreshColourPalette(pal, want);
	}
	pal.WantFind(selforeground, want);
	pal.WantFind(selbackground, want);
	pal.WantFind(selbackground2, want);

	pal.WantFind(foldmarginColour, want);
	pal.WantFind(foldmarginHighlightColour, want);

	pal.WantFind(whitespaceForeground, want);
	pal.WantFind(whitespaceBackground, want);
	pal.WantFind(selbar, want);
	pal.WantFind(selbarlight, want);
	pal.WantFind(caretcolour, want);
	pal.WantFind(caretLineBackground, want);
	pal.WantFind(edgecolour, want);
	pal.WantFind(hotspotForeground, want);
	pal.WantFind(hotspotBackground, want);
}

void ViewStyle::Refresh(Surface &surface) {
	selbar.desired = Platform::Chrome();
	selbarlight.desired = Platform::ChromeHighlight();
	styles[STYLE_DEFAULT].Realise(surface, zoomLevel);
	maxAscent = styles[STYLE_DEFAULT].ascent;
	maxDescent = styles[STYLE_DEFAULT].descent;
	someStylesProtected = false;
	for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
		if (i != STYLE_DEFAULT) {
			styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT]);
			if (maxAscent < styles[i].ascent)
				maxAscent = styles[i].ascent;
			if (maxDescent < styles[i].descent)
				maxDescent = styles[i].descent;
		}
		if (styles[i].IsProtected()) {
			someStylesProtected = true;
		}
	}

	lineHeight = maxAscent + maxDescent;
	aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
	spaceWidth = styles[STYLE_DEFAULT].spaceWidth;

	fixedColumnWidth = leftMarginWidth;
	symbolMargin = false;
	maskInLine = 0xffffffff;
	for (int margin=0; margin < margins; margin++) {
		fixedColumnWidth += ms[margin].width;
		symbolMargin = symbolMargin || ms[margin].symbol;
		if (ms[margin].width > 0)
			maskInLine &= ~ms[margin].mask;
	}
}

void ViewStyle::ResetDefaultStyle() {
	styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
		ColourDesired(0xff,0xff,0xff),
	        Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
		SC_CHARSET_DEFAULT,
		false, false, false, false, Style::caseMixed, true, true, false);
}

void ViewStyle::ClearStyles() {
	// Reset all styles to be like the default style
	for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
		if (i != STYLE_DEFAULT) {
			styles[i].ClearTo(styles[STYLE_DEFAULT]);
		}
	}
	styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
}

void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
	styles[styleIndex].fontName = fontNames.Save(name);
}

bool ViewStyle::ProtectionActive() const {
    return someStylesProtected;
}
<commit_msg>Ensure someStylesProtected is initialised.<commit_after>// Scintilla source code edit control
/** @file ViewStyle.cxx
 ** Store information on how the document is to be viewed.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"

MarginStyle::MarginStyle() :
	symbol(false), width(16), mask(0xffffffff), sensitive(false) {
}

// A list of the fontnames - avoids wasting space in each style
FontNames::FontNames() {
	max = 0;
}

FontNames::~FontNames() {
	Clear();
}

void FontNames::Clear() {
	for (int i=0;i<max;i++) {
		delete []names[i];
	}
	max = 0;
}

const char *FontNames::Save(const char *name) {
	if (!name)
		return 0;
	for (int i=0;i<max;i++) {
		if (strcmp(names[i], name) == 0) {
			return names[i];
		}
	}
	names[max] = new char[strlen(name) + 1];
	strcpy(names[max], name);
	max++;
	return names[max-1];
}

ViewStyle::ViewStyle() {
	Init();
}

ViewStyle::ViewStyle(const ViewStyle &source) {
	Init();
	for (unsigned int sty=0;sty<(sizeof(styles)/sizeof(styles[0]));sty++) {
		styles[sty] = source.styles[sty];
		// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
		styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
	}
	for (int mrk=0;mrk<=MARKER_MAX;mrk++) {
		markers[mrk] = source.markers[mrk];
	}
	for (int ind=0;ind<=INDIC_MAX;ind++) {
		indicators[ind] = source.indicators[ind];
	}

	selforeset = source.selforeset;
	selforeground.desired = source.selforeground.desired;
	selbackset = source.selbackset;
	selbackground.desired = source.selbackground.desired;
	selbackground2.desired = source.selbackground2.desired;

	foldmarginColourSet = source.foldmarginColourSet;
	foldmarginColour.desired = source.foldmarginColour.desired;
	foldmarginHighlightColourSet = source.foldmarginHighlightColourSet;
	foldmarginHighlightColour.desired = source.foldmarginHighlightColour.desired;

	hotspotForegroundSet = source.hotspotForegroundSet;
	hotspotForeground.desired = source.hotspotForeground.desired;
	hotspotBackgroundSet = source.hotspotBackgroundSet;
	hotspotBackground.desired = source.hotspotBackground.desired;
	hotspotUnderline = source.hotspotUnderline;
	hotspotSingleLine = source.hotspotSingleLine;

	whitespaceForegroundSet = source.whitespaceForegroundSet;
	whitespaceForeground.desired = source.whitespaceForeground.desired;
	whitespaceBackgroundSet = source.whitespaceBackgroundSet;
	whitespaceBackground.desired = source.whitespaceBackground.desired;
	selbar.desired = source.selbar.desired;
	selbarlight.desired = source.selbarlight.desired;
	caretcolour.desired = source.caretcolour.desired;
	showCaretLineBackground = source.showCaretLineBackground;
	caretLineBackground.desired = source.caretLineBackground.desired;
	edgecolour.desired = source.edgecolour.desired;
	edgeState = source.edgeState;
	caretWidth = source.caretWidth;
	someStylesProtected = false;
	leftMarginWidth = source.leftMarginWidth;
	rightMarginWidth = source.rightMarginWidth;
	for (int i=0;i < margins; i++) {
		ms[i] = source.ms[i];
	}
	symbolMargin = source.symbolMargin;
	maskInLine = source.maskInLine;
	fixedColumnWidth = source.fixedColumnWidth;
	zoomLevel = source.zoomLevel;
	viewWhitespace = source.viewWhitespace;
	viewIndentationGuides = source.viewIndentationGuides;
	viewEOL = source.viewEOL;
	showMarkedLines = source.showMarkedLines;
}

ViewStyle::~ViewStyle() {
}

void ViewStyle::Init() {
	fontNames.Clear();
	ResetDefaultStyle();

	indicators[0].style = INDIC_SQUIGGLE;
	indicators[0].fore = ColourDesired(0, 0x7f, 0);
	indicators[1].style = INDIC_TT;
	indicators[1].fore = ColourDesired(0, 0, 0xff);
	indicators[2].style = INDIC_PLAIN;
	indicators[2].fore = ColourDesired(0xff, 0, 0);

	lineHeight = 1;
	maxAscent = 1;
	maxDescent = 1;
	aveCharWidth = 8;
	spaceWidth = 8;

	selforeset = false;
	selforeground.desired = ColourDesired(0xff, 0, 0);
	selbackset = true;
	selbackground.desired = ColourDesired(0xc0, 0xc0, 0xc0);
	selbackground2.desired = ColourDesired(0xb0, 0xb0, 0xb0);

	foldmarginColourSet = false;
	foldmarginColour.desired = ColourDesired(0xff, 0, 0);
	foldmarginHighlightColourSet = false;
	foldmarginHighlightColour.desired = ColourDesired(0xc0, 0xc0, 0xc0);

	whitespaceForegroundSet = false;
	whitespaceForeground.desired = ColourDesired(0, 0, 0);
	whitespaceBackgroundSet = false;
	whitespaceBackground.desired = ColourDesired(0xff, 0xff, 0xff);
	selbar.desired = Platform::Chrome();
	selbarlight.desired = Platform::ChromeHighlight();
	styles[STYLE_LINENUMBER].fore.desired = ColourDesired(0, 0, 0);
	styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
	caretcolour.desired = ColourDesired(0, 0, 0);
	showCaretLineBackground = false;
	caretLineBackground.desired = ColourDesired(0xff, 0xff, 0);
	edgecolour.desired = ColourDesired(0xc0, 0xc0, 0xc0);
	edgeState = EDGE_NONE;
	caretWidth = 1;
	someStylesProtected = false;

	hotspotForegroundSet = false;
	hotspotForeground.desired = ColourDesired(0, 0, 0xff);
	hotspotBackgroundSet = false;
	hotspotBackground.desired = ColourDesired(0xff, 0xff, 0xff);
	hotspotUnderline = true;
	hotspotSingleLine = true;

	leftMarginWidth = 1;
	rightMarginWidth = 1;
	ms[0].symbol = false;
	ms[0].width = 0;
	ms[0].mask = 0;
	ms[1].symbol = true;
	ms[1].width = 16;
	ms[1].mask = ~SC_MASK_FOLDERS;
	ms[2].symbol = true;
	ms[2].width = 0;
	ms[2].mask = 0;
	fixedColumnWidth = leftMarginWidth;
	symbolMargin = false;
	maskInLine = 0xffffffff;
	for (int margin=0; margin < margins; margin++) {
		fixedColumnWidth += ms[margin].width;
		symbolMargin = symbolMargin || ms[margin].symbol;
		if (ms[margin].width > 0)
			maskInLine &= ~ms[margin].mask;
	}
	zoomLevel = 0;
	viewWhitespace = wsInvisible;
	viewIndentationGuides = false;
	viewEOL = false;
	showMarkedLines = true;
}

void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
	unsigned int i;
	for (i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
		pal.WantFind(styles[i].fore, want);
		pal.WantFind(styles[i].back, want);
	}
	for (i=0;i<(sizeof(indicators)/sizeof(indicators[0]));i++) {
		pal.WantFind(indicators[i].fore, want);
	}
	for (i=0;i<(sizeof(markers)/sizeof(markers[0]));i++) {
		markers[i].RefreshColourPalette(pal, want);
	}
	pal.WantFind(selforeground, want);
	pal.WantFind(selbackground, want);
	pal.WantFind(selbackground2, want);

	pal.WantFind(foldmarginColour, want);
	pal.WantFind(foldmarginHighlightColour, want);

	pal.WantFind(whitespaceForeground, want);
	pal.WantFind(whitespaceBackground, want);
	pal.WantFind(selbar, want);
	pal.WantFind(selbarlight, want);
	pal.WantFind(caretcolour, want);
	pal.WantFind(caretLineBackground, want);
	pal.WantFind(edgecolour, want);
	pal.WantFind(hotspotForeground, want);
	pal.WantFind(hotspotBackground, want);
}

void ViewStyle::Refresh(Surface &surface) {
	selbar.desired = Platform::Chrome();
	selbarlight.desired = Platform::ChromeHighlight();
	styles[STYLE_DEFAULT].Realise(surface, zoomLevel);
	maxAscent = styles[STYLE_DEFAULT].ascent;
	maxDescent = styles[STYLE_DEFAULT].descent;
	someStylesProtected = false;
	for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
		if (i != STYLE_DEFAULT) {
			styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT]);
			if (maxAscent < styles[i].ascent)
				maxAscent = styles[i].ascent;
			if (maxDescent < styles[i].descent)
				maxDescent = styles[i].descent;
		}
		if (styles[i].IsProtected()) {
			someStylesProtected = true;
		}
	}

	lineHeight = maxAscent + maxDescent;
	aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
	spaceWidth = styles[STYLE_DEFAULT].spaceWidth;

	fixedColumnWidth = leftMarginWidth;
	symbolMargin = false;
	maskInLine = 0xffffffff;
	for (int margin=0; margin < margins; margin++) {
		fixedColumnWidth += ms[margin].width;
		symbolMargin = symbolMargin || ms[margin].symbol;
		if (ms[margin].width > 0)
			maskInLine &= ~ms[margin].mask;
	}
}

void ViewStyle::ResetDefaultStyle() {
	styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
		ColourDesired(0xff,0xff,0xff),
	        Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
		SC_CHARSET_DEFAULT,
		false, false, false, false, Style::caseMixed, true, true, false);
}

void ViewStyle::ClearStyles() {
	// Reset all styles to be like the default style
	for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
		if (i != STYLE_DEFAULT) {
			styles[i].ClearTo(styles[STYLE_DEFAULT]);
		}
	}
	styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
}

void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
	styles[styleIndex].fontName = fontNames.Save(name);
}

bool ViewStyle::ProtectionActive() const {
    return someStylesProtected;
}
<|endoftext|>


<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.0.0, packaged on August, 2008.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_camera.cpp Implementation of the GLC_Camera class.

#include "glc_camera.h"
#include "glc_openglexception.h"

#include <QtDebug>

using namespace glc;
//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////
GLC_Camera::GLC_Camera()
: GLC_Object("Camera")
, m_Eye(0,0,1)
, m_Target()
, m_VectUp(0,1,0)
{

}

GLC_Camera::GLC_Camera(const GLC_Point4d &Eye, const GLC_Point4d &Target, const GLC_Vector4d &Up)
: GLC_Object("Camera")
, m_Eye()
, m_Target()
, m_VectUp()

{
	setCam(Eye, Target, Up);
	createMatComp();
}

// Copy constructor
GLC_Camera::GLC_Camera(const GLC_Camera& cam)
: GLC_Object(cam)
, m_Eye(cam.m_Eye)
, m_Target(cam.m_Target)
, m_VectUp(cam.m_VectUp)
, m_MatCompOrbit(cam.m_MatCompOrbit)
{

}

/////////////////////////////////////////////////////////////////////
// Get Functions
/////////////////////////////////////////////////////////////////////

// Get the distance between the eye and the target of camera
double GLC_Camera::getDistEyeTarget(void) const
{
	return (m_Eye - m_Target).getNorm();
}

// Get camera's eye coordinate point
const GLC_Point4d GLC_Camera::getEye(void) const
{
	return m_Eye;
}

// Get camera's target coordinate point
const GLC_Point4d GLC_Camera::getTarget(void) const
{
	return m_Target;
}

// Get camera's Up vector
const GLC_Vector4d GLC_Camera::getVectUp(void) const
{
	return m_VectUp;
}

// Get camera's Vector (from eye to target)
GLC_Vector4d GLC_Camera::getVectCam(void) const
{
	return m_Eye - m_Target;
}

// Get camera's orbit composition matrix
const GLC_Matrix4x4 GLC_Camera::getMatCompOrbit(void) const
{
	return m_MatCompOrbit;
}

// equality operator
bool GLC_Camera::operator==(const GLC_Camera& cam) const
{
	return (m_Eye == cam.m_Eye) && (m_Target == cam.m_Target)
			&& (m_VectUp == cam.m_VectUp);
}

/////////////////////////////////////////////////////////////////////
// Set Functions
/////////////////////////////////////////////////////////////////////
void GLC_Camera::orbit(GLC_Vector4d VectOldPoss, GLC_Vector4d VectCurPoss)
{
	// Map Vectors
	VectOldPoss= m_MatCompOrbit * VectOldPoss;
	VectCurPoss= m_MatCompOrbit * VectCurPoss;

	// Compute rotation matrix
	const GLC_Vector4d VectAxeRot(VectCurPoss ^ VectOldPoss);
	// Check if rotation vector is not null
	if (!VectAxeRot.isNull())
	{  // Ok, is not null
		const double Angle= acos(VectCurPoss * VectOldPoss);
		const GLC_Matrix4x4 MatOrbit(VectAxeRot, Angle);

		// Camera transformation
		m_Eye= (MatOrbit * (m_Eye - m_Target)) + m_Target;
		m_VectUp= MatOrbit * m_VectUp;
		m_MatCompOrbit= MatOrbit * m_MatCompOrbit;
	}
}

void GLC_Camera::pan(GLC_Vector4d VectDep)
{
	// Vector mapping
	VectDep= m_MatCompOrbit * VectDep;

	// Camera transformation
	m_Eye= m_Eye + VectDep;
	m_Target= m_Target + VectDep;
}

void GLC_Camera::zoom(double factor)
{
	Q_ASSERT(factor > 0);
	// Eye->target vector
	GLC_Vector4d VectCam(m_Eye - m_Target);

	// Compute new vector length
	const double Norme= VectCam.getNorm() * 1 / factor;
	VectCam.setNormal(Norme);

	m_Eye= VectCam + m_Target;

}

void GLC_Camera::move(const GLC_Matrix4x4 &MatMove)
{
	m_Eye= MatMove * m_Eye;
	m_Target= MatMove * m_Target;

	// Up vector computation
	// In case of translation in matrix
	const GLC_Vector4d VectOrigine(0,0,0);
	// Backup m_VectUp
	const GLC_Vector4d VectUpOld(m_VectUp);
	m_VectUp= (MatMove * VectUpOld) - (MatMove * VectOrigine); // Up Vector Origin must be equal to 0,0,0
	createMatComp();
}

void GLC_Camera::translate(const GLC_Vector4d &VectTrans)
{
	m_Eye= m_Eye + VectTrans;
	m_Target= m_Target + VectTrans;
}

void GLC_Camera::setEyeCam(const GLC_Point4d &Eye)
{
	// Old camera's vector
	GLC_Vector4d VectOldCam(m_Eye - m_Target);
	// New camera's vector
	GLC_Vector4d VectCam(Eye - m_Target);
	if ( !(VectOldCam - VectCam).isNull() )
	{
		VectOldCam.setNormal(1);
		VectCam.setNormal(1);
		const double Angle= acos(VectOldCam * VectCam);
		if ( (Angle > EPSILON) && ( (PI - Angle) > EPSILON) )
		{
			const GLC_Vector4d VectAxeRot(VectOldCam ^ VectCam);
			const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
			m_VectUp= MatRot * m_VectUp;
		}
		else
		{
			if ( (PI - Angle) < EPSILON)
			{	// Angle de 180�
				m_VectUp.setInv();
			}
		}

		setCam(Eye, m_Target, m_VectUp);
	}
}

void GLC_Camera::setTargetCam(const GLC_Point4d &Target)
{
	// Old camera's vector
	GLC_Vector4d VectOldCam(m_Eye - m_Target);
	// New camera's vector
	GLC_Vector4d VectCam(m_Eye - Target);
	if ( !(VectOldCam - VectCam).isNull() )
	{
		VectOldCam.setNormal(1);
		VectCam.setNormal(1);
		const double Angle= acos(VectOldCam * VectCam);
		if ( (Angle > EPSILON) && ( (PI - Angle) > EPSILON) )
		{
			const GLC_Vector4d VectAxeRot(VectOldCam ^ VectCam);
			const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
			m_VectUp= MatRot * m_VectUp;
		}
		else
		{
			if ( (PI - Angle) < EPSILON)
			{	// Angle of 180�
				m_VectUp.setInv();
			}
		}

		setCam(m_Eye, Target, m_VectUp);
	}
}

void GLC_Camera::setUpCam(const GLC_Vector4d &Up)
{
	if ( !(m_VectUp - Up).isNull() )
	{
		setCam(m_Eye, m_Target, Up);
	}
}

void GLC_Camera::setCam(GLC_Point4d Eye, GLC_Point4d Target, GLC_Vector4d Up)
{
	Up.setNormal(1);

	const GLC_Vector4d VectCam((Eye - Target).setNormal(1));
	const double Angle= acos(VectCam * Up);

	/* m_VectUp and VectCam could not be parallel
	 * m_VectUp could not be NULL
	 * VectCam could not be NULL */
	//Q_ASSERT((Angle > EPSILON) && ((PI - Angle) > EPSILON));
	if ( fabs(Angle - (PI / 2)) > EPSILON)
	{	// Angle not equal to 90�
		const GLC_Vector4d AxeRot(VectCam ^ Up);
		GLC_Matrix4x4 MatRot(AxeRot, PI / 2);
		Up= MatRot * VectCam;
	}

	m_Eye= Eye;
	m_Target= Target;
	m_VectUp= Up;
	createMatComp();
}

//! Set the camera by copying another camera
void GLC_Camera::setCam(const GLC_Camera& cam)
{
	m_Eye= cam.m_Eye;
	m_Target= cam.m_Target;
	m_VectUp= cam.m_VectUp;
	m_MatCompOrbit= cam.m_MatCompOrbit;
}

void GLC_Camera::setDistEyeTarget(double Longueur)
{
    GLC_Vector4d VectCam(m_Eye - m_Target);
    VectCam.setNormal(Longueur);
    m_Eye= VectCam + m_Target;
}
// Assignement operator
GLC_Camera &GLC_Camera::operator=(const GLC_Camera& cam)
{
	GLC_Object::operator=(cam);
	m_Eye= cam.m_Eye;
	m_Target= cam.m_Target;
	m_VectUp= cam.m_VectUp;
	m_MatCompOrbit= cam.m_MatCompOrbit;
	return *this;
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////
void GLC_Camera::glExecute(GLenum Mode)
{
	gluLookAt(m_Eye.getX(), m_Eye.getY(), m_Eye.getZ(),
		m_Target.getX(), m_Target.getY(), m_Target.getZ(),
		m_VectUp.getX(), m_VectUp.getY(), m_VectUp.getZ());

	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Camera::GlExecute ", error);
		throw(OpenGlException);
	}

}

//////////////////////////////////////////////////////////////////////
// Private services Functions
//////////////////////////////////////////////////////////////////////

void GLC_Camera::createMatComp(void)
{
	// Calcule de la matrice de rotation entre VectZ et VectCam
	// Compute rotation matrix between Z axis and camera
	const GLC_Vector4d VectCam((m_Eye - m_Target).setNormal(1));

	if ( fabs( fabs(VectCam.getZ()) - 1.0 ) > EPSILON)
	{ // Camera's vector not equal to Z axis
		const GLC_Vector4d VectAxeRot= (AxeZ ^ VectCam);
		const double Angle= acos(AxeZ * VectCam);
		m_MatCompOrbit.setMatRot(VectAxeRot, Angle);
	}
	else // Camera's Vector equal to Z axis
	{
		if (VectCam.getZ() < 0)
		{

			m_MatCompOrbit.setMatRot(m_VectUp, PI);
		}
		else
			m_MatCompOrbit.setToIdentity();
	}

	// Angle between InitVectUp and m_VectUp
	GLC_Vector4d InitVectUp(0,1,0); // Par d�faut m_VectUp est Y
	InitVectUp= m_MatCompOrbit * InitVectUp;
	// Compute the angle
	const double AngleVectUp= acos(InitVectUp * m_VectUp);

	GLC_Matrix4x4 MatInt; // intermediate matrix

	if (( AngleVectUp > EPSILON) && ( (PI - AngleVectUp) > EPSILON) )

	{ // Angle not equal to 0 or 180�
		const GLC_Vector4d VectAxeRot(InitVectUp ^ m_VectUp);

		MatInt.setMatRot(VectAxeRot, AngleVectUp);
	}
	else	// Angle equal to 0 or 180�
	{
		MatInt.setMatRot(VectCam, AngleVectUp);
	}

	m_MatCompOrbit= MatInt * m_MatCompOrbit;
}

<commit_msg>Fix a bug on windows plateform : Before calcul the angle between to vector, check if these vector are equal.<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.0.0, packaged on August, 2008.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_camera.cpp Implementation of the GLC_Camera class.

#include "glc_camera.h"
#include "glc_openglexception.h"

#include <QtDebug>

using namespace glc;
//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////
GLC_Camera::GLC_Camera()
: GLC_Object("Camera")
, m_Eye(0,0,1)
, m_Target()
, m_VectUp(0,1,0)
{

}

GLC_Camera::GLC_Camera(const GLC_Point4d &Eye, const GLC_Point4d &Target, const GLC_Vector4d &Up)
: GLC_Object("Camera")
, m_Eye()
, m_Target()
, m_VectUp()

{
	setCam(Eye, Target, Up);
	createMatComp();
}

// Copy constructor
GLC_Camera::GLC_Camera(const GLC_Camera& cam)
: GLC_Object(cam)
, m_Eye(cam.m_Eye)
, m_Target(cam.m_Target)
, m_VectUp(cam.m_VectUp)
, m_MatCompOrbit(cam.m_MatCompOrbit)
{

}

/////////////////////////////////////////////////////////////////////
// Get Functions
/////////////////////////////////////////////////////////////////////

// Get the distance between the eye and the target of camera
double GLC_Camera::getDistEyeTarget(void) const
{
	return (m_Eye - m_Target).getNorm();
}

// Get camera's eye coordinate point
const GLC_Point4d GLC_Camera::getEye(void) const
{
	return m_Eye;
}

// Get camera's target coordinate point
const GLC_Point4d GLC_Camera::getTarget(void) const
{
	return m_Target;
}

// Get camera's Up vector
const GLC_Vector4d GLC_Camera::getVectUp(void) const
{
	return m_VectUp;
}

// Get camera's Vector (from eye to target)
GLC_Vector4d GLC_Camera::getVectCam(void) const
{
	return m_Eye - m_Target;
}

// Get camera's orbit composition matrix
const GLC_Matrix4x4 GLC_Camera::getMatCompOrbit(void) const
{
	return m_MatCompOrbit;
}

// equality operator
bool GLC_Camera::operator==(const GLC_Camera& cam) const
{
	return (m_Eye == cam.m_Eye) && (m_Target == cam.m_Target)
			&& (m_VectUp == cam.m_VectUp);
}

/////////////////////////////////////////////////////////////////////
// Set Functions
/////////////////////////////////////////////////////////////////////
void GLC_Camera::orbit(GLC_Vector4d VectOldPoss, GLC_Vector4d VectCurPoss)
{
	// Map Vectors
	VectOldPoss= m_MatCompOrbit * VectOldPoss;
	VectCurPoss= m_MatCompOrbit * VectCurPoss;

	// Compute rotation matrix
	const GLC_Vector4d VectAxeRot(VectCurPoss ^ VectOldPoss);
	// Check if rotation vector is not null
	if (!VectAxeRot.isNull())
	{  // Ok, is not null
		const double Angle= acos(VectCurPoss * VectOldPoss);
		const GLC_Matrix4x4 MatOrbit(VectAxeRot, Angle);

		// Camera transformation
		m_Eye= (MatOrbit * (m_Eye - m_Target)) + m_Target;
		m_VectUp= MatOrbit * m_VectUp;
		m_MatCompOrbit= MatOrbit * m_MatCompOrbit;
	}
}

void GLC_Camera::pan(GLC_Vector4d VectDep)
{
	// Vector mapping
	VectDep= m_MatCompOrbit * VectDep;

	// Camera transformation
	m_Eye= m_Eye + VectDep;
	m_Target= m_Target + VectDep;
}

void GLC_Camera::zoom(double factor)
{
	Q_ASSERT(factor > 0);
	// Eye->target vector
	GLC_Vector4d VectCam(m_Eye - m_Target);

	// Compute new vector length
	const double Norme= VectCam.getNorm() * 1 / factor;
	VectCam.setNormal(Norme);

	m_Eye= VectCam + m_Target;

}

void GLC_Camera::move(const GLC_Matrix4x4 &MatMove)
{
	m_Eye= MatMove * m_Eye;
	m_Target= MatMove * m_Target;

	// Up vector computation
	// In case of translation in matrix
	const GLC_Vector4d VectOrigine(0,0,0);
	// Backup m_VectUp
	const GLC_Vector4d VectUpOld(m_VectUp);
	m_VectUp= (MatMove * VectUpOld) - (MatMove * VectOrigine); // Up Vector Origin must be equal to 0,0,0
	createMatComp();
}

void GLC_Camera::translate(const GLC_Vector4d &VectTrans)
{
	m_Eye= m_Eye + VectTrans;
	m_Target= m_Target + VectTrans;
}

void GLC_Camera::setEyeCam(const GLC_Point4d &Eye)
{
	// Old camera's vector
	GLC_Vector4d VectOldCam(m_Eye - m_Target);
	// New camera's vector
	GLC_Vector4d VectCam(Eye - m_Target);
	if ( !(VectOldCam - VectCam).isNull() )
	{
		VectOldCam.setNormal(1);
		VectCam.setNormal(1);
		const double Angle= acos(VectOldCam * VectCam);
		if ( (Angle > EPSILON) && ( (PI - Angle) > EPSILON) )
		{
			const GLC_Vector4d VectAxeRot(VectOldCam ^ VectCam);
			const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
			m_VectUp= MatRot * m_VectUp;
		}
		else
		{
			if ( (PI - Angle) < EPSILON)
			{	// Angle de 180�
				m_VectUp.setInv();
			}
		}

		setCam(Eye, m_Target, m_VectUp);
	}
}

void GLC_Camera::setTargetCam(const GLC_Point4d &Target)
{
	// Old camera's vector
	GLC_Vector4d VectOldCam(m_Eye - m_Target);
	// New camera's vector
	GLC_Vector4d VectCam(m_Eye - Target);
	if ( !(VectOldCam - VectCam).isNull() )
	{
		VectOldCam.setNormal(1);
		VectCam.setNormal(1);
		const double Angle= acos(VectOldCam * VectCam);
		if ( (Angle > EPSILON) && ( (PI - Angle) > EPSILON) )
		{
			const GLC_Vector4d VectAxeRot(VectOldCam ^ VectCam);
			const GLC_Matrix4x4 MatRot(VectAxeRot, Angle);
			m_VectUp= MatRot * m_VectUp;
		}
		else
		{
			if ( (PI - Angle) < EPSILON)
			{	// Angle of 180�
				m_VectUp.setInv();
			}
		}

		setCam(m_Eye, Target, m_VectUp);
	}
}

void GLC_Camera::setUpCam(const GLC_Vector4d &Up)
{
	if ( !(m_VectUp - Up).isNull() )
	{
		setCam(m_Eye, m_Target, Up);
	}
}

void GLC_Camera::setCam(GLC_Point4d Eye, GLC_Point4d Target, GLC_Vector4d Up)
{
	Up.setNormal(1);

	const GLC_Vector4d VectCam((Eye - Target).setNormal(1));
	const double Angle= acos(VectCam * Up);

	/* m_VectUp and VectCam could not be parallel
	 * m_VectUp could not be NULL
	 * VectCam could not be NULL */
	//Q_ASSERT((Angle > EPSILON) && ((PI - Angle) > EPSILON));
	if ( fabs(Angle - (PI / 2)) > EPSILON)
	{	// Angle not equal to 90�
		const GLC_Vector4d AxeRot(VectCam ^ Up);
		GLC_Matrix4x4 MatRot(AxeRot, PI / 2);
		Up= MatRot * VectCam;
	}

	m_Eye= Eye;
	m_Target= Target;
	m_VectUp= Up;
	createMatComp();
}

//! Set the camera by copying another camera
void GLC_Camera::setCam(const GLC_Camera& cam)
{
	m_Eye= cam.m_Eye;
	m_Target= cam.m_Target;
	m_VectUp= cam.m_VectUp;
	m_MatCompOrbit= cam.m_MatCompOrbit;
}

void GLC_Camera::setDistEyeTarget(double Longueur)
{
    GLC_Vector4d VectCam(m_Eye - m_Target);
    VectCam.setNormal(Longueur);
    m_Eye= VectCam + m_Target;
}
// Assignement operator
GLC_Camera &GLC_Camera::operator=(const GLC_Camera& cam)
{
	GLC_Object::operator=(cam);
	m_Eye= cam.m_Eye;
	m_Target= cam.m_Target;
	m_VectUp= cam.m_VectUp;
	m_MatCompOrbit= cam.m_MatCompOrbit;
	return *this;
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////
void GLC_Camera::glExecute(GLenum Mode)
{
	gluLookAt(m_Eye.getX(), m_Eye.getY(), m_Eye.getZ(),
		m_Target.getX(), m_Target.getY(), m_Target.getZ(),
		m_VectUp.getX(), m_VectUp.getY(), m_VectUp.getZ());

	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Camera::GlExecute ", error);
		throw(OpenGlException);
	}

}

//////////////////////////////////////////////////////////////////////
// Private services Functions
//////////////////////////////////////////////////////////////////////

void GLC_Camera::createMatComp(void)
{
	// Compute rotation matrix between Z axis and camera
	const GLC_Vector4d VectCam((m_Eye - m_Target).setNormal(1));

	if ( fabs( fabs(VectCam.getZ()) - 1.0 ) > EPSILON)
	{ // Camera's vector not equal to Z axis
		const GLC_Vector4d VectAxeRot= (AxeZ ^ VectCam);
		const double Angle= acos(AxeZ * VectCam);
		m_MatCompOrbit.setMatRot(VectAxeRot, Angle);
	}
	else // Camera's Vector equal to Z axis
	{
		if (VectCam.getZ() < 0)
		{

			m_MatCompOrbit.setMatRot(m_VectUp, PI);
		}
		else
			m_MatCompOrbit.setToIdentity();
	}

	// Angle between InitVectUp and m_VectUp
	GLC_Vector4d InitVectUp(0,1,0); // m_VectUp is Y by default
	InitVectUp= m_MatCompOrbit * InitVectUp;
	// Compute the angle if vector are not equal
	if (InitVectUp != InitVectUp)
	{
		const double AngleVectUp= acos(InitVectUp * m_VectUp);

		GLC_Matrix4x4 MatInt; // intermediate matrix

		if (( AngleVectUp > EPSILON) && ( (PI - AngleVectUp) > EPSILON) )

		{ // Angle not equal to 0 or 180
			const GLC_Vector4d VectAxeRot(InitVectUp ^ m_VectUp);
			MatInt.setMatRot(VectAxeRot, AngleVectUp);
		}
		else	// Angle equal to 0 or 180
		{
			MatInt.setMatRot(VectCam, AngleVectUp);
		}
		qDebug() << "MatInt " << MatInt.toString();
		m_MatCompOrbit= MatInt * m_MatCompOrbit;
	}
}

<|endoftext|>


<commit_before>#include <iomanip>
#include "performance.h"

using namespace std;
using namespace cv;

void Test::gen(Mat& mat, int rows, int cols, int type, Scalar low, Scalar high)
{
    mat.create(rows, cols, type);

    RNG rng(0);
    rng.fill(mat, RNG::UNIFORM, low, high);
}

void Test::gen(Mat& mat, int rows, int cols, int type)
{
    mat.create(rows, cols, type);

    Mat mat8u(rows, cols * mat.elemSize(), CV_8U, mat.data, mat.step);

    RNG rng(0);
    rng.fill(mat, RNG::UNIFORM, Scalar(0), Scalar(256));
}

void TestSystem::run()
{
    cout << setiosflags(ios_base::left);
    cout << "    " << setw(10) << "CPU, ms" << setw(10) << "GPU, ms"
        << setw(10) << "SPEEDUP" << "DESCRIPTION\n";
    cout << resetiosflags(ios_base::left);

    vector<Test*>::iterator it = tests_.begin();
    for (; it != tests_.end(); ++it)
    {
        can_flush_ = false;
        Test* test = *it;

        cout << endl << test->name() << ":\n";
        test->run();

        flush();
    }

    cout << setiosflags(ios_base::fixed | ios_base::left);
    cout << "\nCPU Total: " << setprecision(3) << cpu_total_ / getTickFrequency() << " sec\n";
    cout << "GPU Total: " << setprecision(3) << gpu_total_ / getTickFrequency() << " sec (x"
        << setprecision(3) << (double)cpu_total_ / gpu_total_ << ")\n";
    cout << resetiosflags(ios_base::fixed | ios_base::left);
}

void TestSystem::flush()
{
    if (!can_flush_)
        return;

    int cpu_time = static_cast<int>(cpu_elapsed_ / getTickFrequency() * 1000.0);
    int gpu_time = static_cast<int>(gpu_elapsed_ / getTickFrequency() * 1000.0);
    double speedup = (double)cpu_time / gpu_time;

    cpu_elapsed_ = 0;
    gpu_elapsed_ = 0;

    cout << "    " << setiosflags(ios_base::fixed | ios_base::left);

    stringstream stream;
    stream << cpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << gpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << "x" << setprecision(3) << speedup;
    cout << setw(10) << stream.str();

    cout << description_.str();
    description_.str("");

    cout << resetiosflags(ios_base::fixed | ios_base::left) << endl;
    can_flush_ = false;
}

int main()
{
    TestSystem::instance()->run();
    return 0;
}<commit_msg>minor refactoring of gpu perf. tests<commit_after>#include <iomanip>
#include "performance.h"

using namespace std;
using namespace cv;

void Test::gen(Mat& mat, int rows, int cols, int type, Scalar low, Scalar high)
{
    mat.create(rows, cols, type);

    RNG rng(0);
    rng.fill(mat, RNG::UNIFORM, low, high);
}

void Test::gen(Mat& mat, int rows, int cols, int type)
{
    mat.create(rows, cols, type);

    Mat mat8u(rows, cols * mat.elemSize(), CV_8U, mat.data, mat.step);

    RNG rng(0);
    rng.fill(mat, RNG::UNIFORM, Scalar(0), Scalar(256));
}

void TestSystem::run()
{
    cout << setiosflags(ios_base::left);
    cout << "    " << setw(10) << "CPU, ms" << setw(10) << "GPU, ms"
        << setw(10) << "SPEEDUP" << "DESCRIPTION\n";
    cout << resetiosflags(ios_base::left);

    vector<Test*>::iterator it = tests_.begin();
    for (; it != tests_.end(); ++it)
    {
        can_flush_ = false;
        Test* test = *it;

        cout << endl << test->name() << ":\n";
        test->run();

        flush();
    }

    cout << setiosflags(ios_base::fixed | ios_base::left);
    cout << "\nCPU Total: " << setprecision(3) << cpu_total_ / getTickFrequency() << " sec\n";
    cout << "GPU Total: " << setprecision(3) << gpu_total_ / getTickFrequency() << " sec (x"
        << setprecision(3) << static_cast<double>(cpu_total_) / gpu_total_ << ")\n";
    cout << resetiosflags(ios_base::fixed | ios_base::left);
}

void TestSystem::flush()
{
    if (!can_flush_)
        return;

    int cpu_time = static_cast<int>(cpu_elapsed_ / getTickFrequency() * 1000.0);
    int gpu_time = static_cast<int>(gpu_elapsed_ / getTickFrequency() * 1000.0);
    double speedup = static_cast<double>(cpu_time) / gpu_time;

    cpu_elapsed_ = 0;
    gpu_elapsed_ = 0;

    cout << "    " << setiosflags(ios_base::fixed | ios_base::left);

    stringstream stream;
    stream << cpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << gpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << "x" << setprecision(3) << speedup;
    cout << setw(10) << stream.str();

    cout << description_.str();
    description_.str("");

    cout << resetiosflags(ios_base::fixed | ios_base::left) << endl;
    can_flush_ = false;
}

int main()
{
    TestSystem::instance()->run();
    return 0;
}<|endoftext|>


<commit_before>#ifndef MJOLNIR_POTENTIAL_GLOBAL_ISOLF_ATTRACTIVE_POTENTIAL_HPP
#define MJOLNIR_POTENTIAL_GLOBAL_ISOLF_ATTRACTIVE_POTENTIAL_HPP
#include <mjolnir/core/ExclusionList.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/math/math.hpp>
#include <vector>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <cmath>

namespace mjolnir
{

// attractive part of the iSoLF potential for coarse-grained lipids developed by
// - Diego Ugarte La Torre and Shoji Takada (2020)
//
// This class contains sigmas, epsilons, and omegas of the particles and
// calculates energy and derivative of the potential function.
template<typename traitsT>
class iSoLFAttractivePotential
{
  public:
    using traits_type          = traitsT;
    using real_type            = typename traits_type::real_type;
    using system_type          = System<traits_type>;
    using parameter_type       = std::tuple<real_type, real_type, real_type>;
    using container_type       = std::vector<parameter_type>;

    // cache sigma_ij, epsilon_ij, omega_ij, 1 / 2omega_ij.
    using pair_parameter_type  = std::tuple<real_type, real_type, real_type, real_type>;

    // topology stuff
    using topology_type        = Topology;
    using molecule_id_type     = typename topology_type::molecule_id_type;
    using group_id_type        = typename topology_type::group_id_type;
    using connection_kind_type = typename topology_type::connection_kind_type;
    using ignore_molecule_type = IgnoreMolecule<molecule_id_type>;
    using ignore_group_type    = IgnoreGroup   <group_id_type>;
    using exclusion_list_type  = ExclusionList <traits_type>;

    static constexpr parameter_type default_parameter() noexcept
    {
        return parameter_type{real_type(0), real_type(0), real_type(0)};
    }

  public:

    iSoLFAttractivePotential(
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
    : exclusion_list_(exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {
        this->parameters_  .reserve(parameters.size());
        this->participants_.reserve(parameters.size());
        for(const auto& idxp : parameters)
        {
            const auto idx = idxp.first;
            this->participants_.push_back(idx);
            if(idx >= this->parameters_.size())
            {
                this->parameters_.resize(idx+1, default_parameter());
            }
            this->parameters_.at(idx) = idxp.second;
        }
    }
    ~iSoLFAttractivePotential() = default;

    pair_parameter_type prepare_params(std::size_t i, std::size_t j) const noexcept
    {
        const auto sgm1 = std::get<0>(parameters_[i]);
        const auto eps1 = std::get<1>(parameters_[i]);
        const auto omg1 = std::get<2>(parameters_[i]);

        const auto sgm2 = std::get<0>(parameters_[j]);
        const auto eps2 = std::get<1>(parameters_[j]);
        const auto omg2 = std::get<2>(parameters_[j]);

        return std::make_tuple((sgm1 + sgm2) / 2,
                              ((eps1 == eps2) ? eps1 : std::sqrt(eps1 * eps2)),
                               (omg1 + omg2) / 2,
                               real_type(1.0) / (omg1 + omg2));
    }

    // forwarding functions for clarity...
    real_type potential(const std::size_t i, const std::size_t j,
                        const real_type r) const noexcept
    {
        return this->potential(r, this->prepare_params(i, j));
    }
    real_type derivative(const std::size_t i, const std::size_t j,
                         const real_type r) const noexcept
    {
        return this->derivative(r, this->prepare_params(i, j));
    }

    real_type potential(const real_type r, const pair_parameter_type& p) const noexcept
    {
        constexpr real_type rc = 1.12246204831;
        constexpr real_type pi = math::constants<real_type>::pi();

        const real_type sigma   = std::get<0>(p);
        const real_type epsilon = std::get<1>(p);
        const real_type omega   = std::get<2>(p);

        const real_type r_sigma_rc = r - sigma * rc; // r - sqrt[6]{2} sigma

        if     (r_sigma_rc <= 0)   {return -epsilon;}
        else if(omega < r_sigma_rc){return 0;}

        const real_type romega = std::get<3>(p); // 1 / 2omega_ij
        const real_type cosine = std::cos(pi * romega * r_sigma_rc);

        return -epsilon * cosine * cosine;
    }
    real_type derivative(const real_type r, const pair_parameter_type& p) const noexcept
    {
        constexpr real_type rc = 1.12246204831;
        constexpr real_type pi = math::constants<real_type>::pi();

        const real_type sigma   = std::get<0>(p);
        const real_type epsilon = std::get<1>(p);
        const real_type omega   = std::get<2>(p);

        const real_type r_sigma_rc = r - sigma * rc; // r - sqrt[6]{2} sigma

        if (r_sigma_rc <= 0 || omega < r_sigma_rc) {return 0;}

        const real_type romega = std::get<3>(p); // 1 / 2omega_ij
        const real_type sine   = std::sin(2 * pi * romega * r_sigma_rc);

        return epsilon * pi * romega * sine;
    }

    real_type cutoff_ratio()   const noexcept {return std::numeric_limits<real_type>::infinity();}
    real_type coef_at_cutoff() const noexcept {return 0.0;}

    real_type max_cutoff_length() const noexcept
    {
        constexpr real_type rc = 1.12246204831; // sqrt[6]{2}

        if(this->parameters_.empty())
        {
            return 0.0;
        }

        const real_type max_sigma = std::get<0>(*std::max_element(
            this->parameters_.cbegin(), this->parameters_.cend(),
            [](const parameter_type& lhs, const parameter_type& rhs) noexcept {
                return std::get<0>(lhs) < std::get<0>(rhs);
            }));
        const real_type max_omega = std::get<2>(*std::max_element(
            this->parameters_.cbegin(), this->parameters_.cend(),
            [](const parameter_type& lhs, const parameter_type& rhs) noexcept {
                return std::get<2>(lhs) < std::get<2>(rhs);
            }));

        return max_sigma * rc + max_omega;
    }

    void initialize(const system_type& sys, const topology_type& topol) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->update(sys, topol);
        return;
    }

    void update(const system_type& sys, const topology_type& topol) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        // update exclusion list based on sys.topology()
        exclusion_list_.make(sys, topol);
        return;
    }

    // -----------------------------------------------------------------------
    // for spatial partitions
    //
    // Here, the default implementation uses Newton's 3rd law to reduce
    // calculation. For an interacting pair (i, j), forces applied to i and j
    // are equal in magnitude and opposite in direction. So, if a pair (i, j) is
    // listed, (j, i) is not needed.
    //     See implementation of VerletList, CellList and GlobalPairInteraction
    // for more details about the usage of these functions.

    std::vector<std::size_t> const& participants() const noexcept {return participants_;}

    range<typename std::vector<std::size_t>::const_iterator>
    leading_participants() const noexcept
    {
        return make_range(participants_.begin(), std::prev(participants_.end()));
    }
    range<typename std::vector<std::size_t>::const_iterator>
    possible_partners_of(const std::size_t participant_idx,
                         const std::size_t /*particle_idx*/) const noexcept
    {
        return make_range(participants_.begin() + participant_idx + 1, participants_.end());
    }
    bool has_interaction(const std::size_t i, const std::size_t j) const noexcept
    {
        // if not excluded, the pair has interaction.
        return (i < j) && !exclusion_list_.is_excluded(i, j);
    }
    // for testing
    exclusion_list_type const& exclusion_list() const noexcept
    {
        return exclusion_list_;
    }

    // ------------------------------------------------------------------------
    // used by Observer.
    static const char* name() noexcept {return "iSoLF";}

    // ------------------------------------------------------------------------
    // the following accessers would be used in tests.

    // access to the parameters...
    std::vector<parameter_type>&       parameters()       noexcept {return parameters_;}
    std::vector<parameter_type> const& parameters() const noexcept {return parameters_;}

  private:

    container_type parameters_;
    std::vector<std::size_t> participants_;
    exclusion_list_type  exclusion_list_;
};

} // mjolnir

#ifdef MJOLNIR_SEPARATE_BUILD
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/BoundaryCondition.hpp>

namespace mjolnir
{
extern template class iSoLFAttractivePotential<SimulatorTraits<double, UnlimitedBoundary>       >;
extern template class iSoLFAttractivePotential<SimulatorTraits<float,  UnlimitedBoundary>       >;
extern template class iSoLFAttractivePotential<SimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class iSoLFAttractivePotential<SimulatorTraits<float,  CuboidalPeriodicBoundary>>;
} // mjolnir
#endif// MJOLNIR_SEPARATE_BUILD

#endif /* MJOLNIR_ISOLF_ATTRACTIVE_POTENTIAL */
<commit_msg>chore: add bibliographic info<commit_after>#ifndef MJOLNIR_POTENTIAL_GLOBAL_ISOLF_ATTRACTIVE_POTENTIAL_HPP
#define MJOLNIR_POTENTIAL_GLOBAL_ISOLF_ATTRACTIVE_POTENTIAL_HPP
#include <mjolnir/core/ExclusionList.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/math/math.hpp>
#include <vector>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <cmath>

namespace mjolnir
{

// attractive part of the iSoLF potential for coarse-grained lipids developed by
// - Diego Ugarte La Torre and Shoji Takada (2020) J. Chem. Phys 153, 205101
//   https://doi.org/10.1063/5.0026342
//
// This class contains sigmas, epsilons, and omegas of the particles and
// calculates energy and derivative of the potential function.
template<typename traitsT>
class iSoLFAttractivePotential
{
  public:
    using traits_type          = traitsT;
    using real_type            = typename traits_type::real_type;
    using system_type          = System<traits_type>;
    using parameter_type       = std::tuple<real_type, real_type, real_type>;
    using container_type       = std::vector<parameter_type>;

    // cache sigma_ij, epsilon_ij, omega_ij, 1 / 2omega_ij.
    using pair_parameter_type  = std::tuple<real_type, real_type, real_type, real_type>;

    // topology stuff
    using topology_type        = Topology;
    using molecule_id_type     = typename topology_type::molecule_id_type;
    using group_id_type        = typename topology_type::group_id_type;
    using connection_kind_type = typename topology_type::connection_kind_type;
    using ignore_molecule_type = IgnoreMolecule<molecule_id_type>;
    using ignore_group_type    = IgnoreGroup   <group_id_type>;
    using exclusion_list_type  = ExclusionList <traits_type>;

    static constexpr parameter_type default_parameter() noexcept
    {
        return parameter_type{real_type(0), real_type(0), real_type(0)};
    }

  public:

    iSoLFAttractivePotential(
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
    : exclusion_list_(exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {
        this->parameters_  .reserve(parameters.size());
        this->participants_.reserve(parameters.size());
        for(const auto& idxp : parameters)
        {
            const auto idx = idxp.first;
            this->participants_.push_back(idx);
            if(idx >= this->parameters_.size())
            {
                this->parameters_.resize(idx+1, default_parameter());
            }
            this->parameters_.at(idx) = idxp.second;
        }
    }
    ~iSoLFAttractivePotential() = default;

    pair_parameter_type prepare_params(std::size_t i, std::size_t j) const noexcept
    {
        const auto sgm1 = std::get<0>(parameters_[i]);
        const auto eps1 = std::get<1>(parameters_[i]);
        const auto omg1 = std::get<2>(parameters_[i]);

        const auto sgm2 = std::get<0>(parameters_[j]);
        const auto eps2 = std::get<1>(parameters_[j]);
        const auto omg2 = std::get<2>(parameters_[j]);

        return std::make_tuple((sgm1 + sgm2) / 2,
                              ((eps1 == eps2) ? eps1 : std::sqrt(eps1 * eps2)),
                               (omg1 + omg2) / 2,
                               real_type(1.0) / (omg1 + omg2));
    }

    // forwarding functions for clarity...
    real_type potential(const std::size_t i, const std::size_t j,
                        const real_type r) const noexcept
    {
        return this->potential(r, this->prepare_params(i, j));
    }
    real_type derivative(const std::size_t i, const std::size_t j,
                         const real_type r) const noexcept
    {
        return this->derivative(r, this->prepare_params(i, j));
    }

    real_type potential(const real_type r, const pair_parameter_type& p) const noexcept
    {
        constexpr real_type rc = 1.12246204831;
        constexpr real_type pi = math::constants<real_type>::pi();

        const real_type sigma   = std::get<0>(p);
        const real_type epsilon = std::get<1>(p);
        const real_type omega   = std::get<2>(p);

        const real_type r_sigma_rc = r - sigma * rc; // r - sqrt[6]{2} sigma

        if     (r_sigma_rc <= 0)   {return -epsilon;}
        else if(omega < r_sigma_rc){return 0;}

        const real_type romega = std::get<3>(p); // 1 / 2omega_ij
        const real_type cosine = std::cos(pi * romega * r_sigma_rc);

        return -epsilon * cosine * cosine;
    }
    real_type derivative(const real_type r, const pair_parameter_type& p) const noexcept
    {
        constexpr real_type rc = 1.12246204831;
        constexpr real_type pi = math::constants<real_type>::pi();

        const real_type sigma   = std::get<0>(p);
        const real_type epsilon = std::get<1>(p);
        const real_type omega   = std::get<2>(p);

        const real_type r_sigma_rc = r - sigma * rc; // r - sqrt[6]{2} sigma

        if (r_sigma_rc <= 0 || omega < r_sigma_rc) {return 0;}

        const real_type romega = std::get<3>(p); // 1 / 2omega_ij
        const real_type sine   = std::sin(2 * pi * romega * r_sigma_rc);

        return epsilon * pi * romega * sine;
    }

    real_type cutoff_ratio()   const noexcept {return std::numeric_limits<real_type>::infinity();}
    real_type coef_at_cutoff() const noexcept {return 0.0;}

    real_type max_cutoff_length() const noexcept
    {
        constexpr real_type rc = 1.12246204831; // sqrt[6]{2}

        if(this->parameters_.empty())
        {
            return 0.0;
        }

        const real_type max_sigma = std::get<0>(*std::max_element(
            this->parameters_.cbegin(), this->parameters_.cend(),
            [](const parameter_type& lhs, const parameter_type& rhs) noexcept {
                return std::get<0>(lhs) < std::get<0>(rhs);
            }));
        const real_type max_omega = std::get<2>(*std::max_element(
            this->parameters_.cbegin(), this->parameters_.cend(),
            [](const parameter_type& lhs, const parameter_type& rhs) noexcept {
                return std::get<2>(lhs) < std::get<2>(rhs);
            }));

        return max_sigma * rc + max_omega;
    }

    void initialize(const system_type& sys, const topology_type& topol) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->update(sys, topol);
        return;
    }

    void update(const system_type& sys, const topology_type& topol) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        // update exclusion list based on sys.topology()
        exclusion_list_.make(sys, topol);
        return;
    }

    // -----------------------------------------------------------------------
    // for spatial partitions
    //
    // Here, the default implementation uses Newton's 3rd law to reduce
    // calculation. For an interacting pair (i, j), forces applied to i and j
    // are equal in magnitude and opposite in direction. So, if a pair (i, j) is
    // listed, (j, i) is not needed.
    //     See implementation of VerletList, CellList and GlobalPairInteraction
    // for more details about the usage of these functions.

    std::vector<std::size_t> const& participants() const noexcept {return participants_;}

    range<typename std::vector<std::size_t>::const_iterator>
    leading_participants() const noexcept
    {
        return make_range(participants_.begin(), std::prev(participants_.end()));
    }
    range<typename std::vector<std::size_t>::const_iterator>
    possible_partners_of(const std::size_t participant_idx,
                         const std::size_t /*particle_idx*/) const noexcept
    {
        return make_range(participants_.begin() + participant_idx + 1, participants_.end());
    }
    bool has_interaction(const std::size_t i, const std::size_t j) const noexcept
    {
        // if not excluded, the pair has interaction.
        return (i < j) && !exclusion_list_.is_excluded(i, j);
    }
    // for testing
    exclusion_list_type const& exclusion_list() const noexcept
    {
        return exclusion_list_;
    }

    // ------------------------------------------------------------------------
    // used by Observer.
    static const char* name() noexcept {return "iSoLF";}

    // ------------------------------------------------------------------------
    // the following accessers would be used in tests.

    // access to the parameters...
    std::vector<parameter_type>&       parameters()       noexcept {return parameters_;}
    std::vector<parameter_type> const& parameters() const noexcept {return parameters_;}

  private:

    container_type parameters_;
    std::vector<std::size_t> participants_;
    exclusion_list_type  exclusion_list_;
};

} // mjolnir

#ifdef MJOLNIR_SEPARATE_BUILD
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/BoundaryCondition.hpp>

namespace mjolnir
{
extern template class iSoLFAttractivePotential<SimulatorTraits<double, UnlimitedBoundary>       >;
extern template class iSoLFAttractivePotential<SimulatorTraits<float,  UnlimitedBoundary>       >;
extern template class iSoLFAttractivePotential<SimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class iSoLFAttractivePotential<SimulatorTraits<float,  CuboidalPeriodicBoundary>>;
} // mjolnir
#endif// MJOLNIR_SEPARATE_BUILD

#endif /* MJOLNIR_ISOLF_ATTRACTIVE_POTENTIAL */
<|endoftext|>