#include "StdAfx.h"
#include "CameraRecords.h"

#include <fstream>

#include <C2/gl/GlApiExt.h>
#include <C2/gl/GlGeometryFunctions.h>
#include <C2/gl/OpenGLUT/OpenGlutStringExt.h>


bool CameraRecords::SaveCamera(const char* filename)
{
	std::ofstream ofs(filename);
	if(!ofs.is_open())
		return false;

	ofs << (int)m_Records.size() << std::endl;
	for(size_t i = 0; i < m_Records.size(); ++i)
	{
		lib_gl::CameraManipulator& m = m_Records[i];
		ofs << m.m_EyePos.x  << " " << m.m_EyePos.y   << " " << m.m_EyePos.z  << std::endl;
		ofs << m.m_Up.x      << " " << m.m_Up.y       << " " << m.m_Up.z      << std::endl;
		ofs << m.m_ViewPos.x << " " << m.m_ViewPos.y  << " " << m.m_ViewPos.z << std::endl;
	}

	return true;
}

bool CameraRecords::LoadCamera(const char* filename)
{
	std::ifstream ifs(filename);
	if(!ifs.is_open())
		return false;

	int NumCameras;
	ifs >> NumCameras;
	m_Records.clear();
	m_Records.resize(NumCameras);
	for (lib_gl::CameraManipulator& m : m_Records)
	{
		ifs >> m.m_EyePos.x  >> m.m_EyePos.y   >> m.m_EyePos.z;
		ifs >> m.m_Up.x      >> m.m_Up.y       >> m.m_Up.z;
		ifs >> m.m_ViewPos.x >> m.m_ViewPos.y  >> m.m_ViewPos.z;
	}

	return true;
}

void CameraRecords::RecordCamera(gl::Camera& camera)
{
	m_Records.push_back(camera.m_Manip);
}

void CameraRecords::RemoveRecordedCamera(int camera_idx)
{
	std::vector<lib_gl::CameraManipulator>::iterator i;
	i = m_Records.begin();
	i += camera_idx;
	m_Records.erase(i);
}


void CameraRecords::DrawRecordPos(const gl::Camera& cur_camera)
{
	float w = (float)cur_camera.m_Projection.m_Viewport.Width;
	float h = (float)cur_camera.m_Projection.m_Viewport.Height;
	if(w <= 0.0f || h <= 0.0f)
		return;

	float ang = cur_camera.m_Projection.m_Fovy;
	if(ang <= 0.0f)
		return;

	glPushAttrib( GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT );
	glDisable(GL_LIGHTING);
	glPointSize(3.0f);
	glLineWidth(1.0f);

	glColor3d(0, 0.8, 0.8);
	for(size_t i = 0; i < m_Records.size(); ++i)
	{
		const lib_gl::CameraManipulator& manip = m_Records[i];

		const lm::vec3f& e = manip.m_EyePos;
		const lm::vec3f& v = manip.m_ViewPos;
		const lm::vec3f f = manip.GetFront();

		float rect_dst = (v - e).length() * 0.1f;

		float cw, ch;
		cur_camera.m_Projection.GetViewRange(rect_dst, cw, ch);

		const lm::vec3f u = manip.GetUp() * ch;
		const lm::vec3f r = manip.GetBinormal() * cw;

		lm::vec3f rect_pos = e + f * rect_dst;

		lm::vec3f v0 = rect_pos + u + r;
		lm::vec3f v1 = rect_pos + u - r;
		lm::vec3f v2 = rect_pos - u - r;
		lm::vec3f v3 = rect_pos - u + r;

		glBegin(GL_LINE_LOOP);
		glVertex3fv(v0.v());
		glVertex3fv(v1.v());
		glVertex3fv(v2.v());
		glVertex3fv(v3.v());
		glEnd();

		lib_gl::glDrawSegment(e, v0);
		lib_gl::glDrawSegment(e, v1);
		lib_gl::glDrawSegment(e, v2);
		lib_gl::glDrawSegment(e, v3);

		lib_gl::glDrawSegment(e, v);
		lib_gl::glDrawPoint(e);
		lib_gl::glDrawPoint(v);

		glutBitmapStringVal3f(e, i);
	}

	glPopAttrib();
}


void CameraRecords::Clear(void)
{
	m_Records.clear();
}
