// OGL_CAMERA.H : the OpenGL camera class + a transformer class.

// Copyright (C) 1998 Tommi Hassinen.

// This package 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.

// This package 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 this package; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

/*################################################################################################*/

//#include "config.h"

#ifndef OGL_CAMERA_H
#define OGL_CAMERA_H

/*################################################################################################*/

enum rmode { Normal = 0, Transform1 = 1, Transform2 = 2 };

class ogl_camera;

class ogl_transformer;
class ogl_transformer_client;

#include "ogl_objects.h"
#include "base_wnd.h"

/*################################################################################################*/

/**	The "##camera" class holds information about position and orientation of the views 
	in viewing windows. A single camera can pass this information to multiple windows. 
	There can also be "##local lights", lights connected to a camera. If some 
	translations/rotations are done to the camera, these lights will follow...
*/

class ogl_camera :
	public ogl_dummy_object
{
	private:
	
	list<ogl_smart_object *> obj_list;
	
	protected:
	
	vector<base_wcl *> wcl_vector;
	vector<base_wnd *> wnd_vector;
	
	friend class base_wcl;
	friend class base_wnd;
	
	friend class base_app;
	friend class ogl_smart_object;		// for obj_list access...
	
	public:
	
	GLfloat focus;
	GLfloat clipping;
	
	bool update_vdim;
	
	bool use_local_lights;
	bool use_global_lights;
	
	bool ortho;
	bool stereo_mode;	// this is true if any stereo mode; relaxed-eye or color-based.
	bool stereo_relaxed;	// this is true if relaxed_eye stereo mode.
	
	float stereo_displacement;
	float relaxed_separation;
	
	public:
	
	ogl_camera(const ogl_object_location &, GLfloat);
	ogl_camera(const ogl_camera &);
	~ogl_camera(void);
	
	protected:
	
	void RegisterClient(base_wcl *);
	void UnregisterClient(base_wcl *);

	void RegisterWnd(base_wnd *);
	void UnregisterWnd(base_wnd *);
	
	public:
	
	bool CopySettings(const ogl_camera *);
	void RenderScene(base_wnd *, bool, bool, int = -1, int = -1);
	
	const char * GetObjectName(void) { return "camera"; }		// virtual
	
	void OrbitObject(const GLfloat *, const ogl_camera &);		// virtual
	void RotateObject(const GLfloat *, const ogl_camera &);		// virtual
	
	void TranslateObject(const GLfloat *, const ogl_obj_loc_data *);	// virtual
	
	bool BeginTransformation(void) { return false; }	// virtual
	bool EndTransformation(void) { return false; }		// virtual
	
	void Render(void) { }		// virtual
	
	void DoCameraEvents(void);
};

/*################################################################################################*/
/**	The "##transformer" is a special class used only when rotating/translating some 
	selected part of the model. transformer::GetMatrix() is used to get the transformation 
	matrix for making those modifications permanent.
	
	It is useful to switch orbiting and rotating, so that objects will behave similarly to 
	lights and the whole scene...
*/

class ogl_transformer :
	public ogl_dummy_object
{
	public:
	
	static ogl_transformer_client * client;
	static bool transform_in_progress;
	
	public:
	
	ogl_transformer(void);
	~ogl_transformer(void);
	
	void Init(ogl_transformer_client *);
	void GetMatrix(GLfloat *) const;
	
	const char * GetObjectName(void) { return "transformer"; }	// virtual
	
	bool BeginTransformation(void);		// virtual
	bool EndTransformation(void);		// virtual
	
	void OrbitObject(const GLfloat *, const ogl_camera &);		// virtual
	void RotateObject(const GLfloat *, const ogl_camera &);		// virtual
	
	void Render(void) { }		// virtual
};

class ogl_transformer_client
{
	public:
	
	ogl_dummy_object * tc_object_ref;	// the object to be transformed.
	
	public:
	
	ogl_transformer_client(void);
	virtual ~ogl_transformer_client(void);
	
/**	This should center the transformer object to the center of all 
	selected objects, and shift the center of all selected objects 
	to the origo.
*/
	virtual void BeginClientTransformation(ogl_transformer *) = 0;
	
/**	This should get the transformation matrix from the transformer
	object and use it to transform all selected objects to their
	new position and/or orientation.
*/
	virtual void EndClientTransformation(ogl_transformer *) = 0;
};

/*################################################################################################*/

#endif	// OGL_CAMERA_H

// eof
