// OGL_OBJECTS.H : base classes for different OpenGL-objects.

// 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_OBJECTS_H
#define OGL_OBJECTS_H

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

#ifdef WIN32
#include <windows.h>	// need to have this before the GL stuff...
#endif	// WIN32

#include <GL/gl.h>
#include <GL/glu.h>

#include <list>
#include <vector>
using namespace std;

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

struct ogl_obj_loc_data;

class ogl_dummy_object;
class ogl_smart_object;

class ogl_object_location;

class ogl_ol_static;
class ogl_ol_dynamic_l1;

#include "oglv3d.h"

class ogl_camera;	// ogl_camera.h

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

/**	This function can be used to modify a 3D-vector object using a 4x4 transformation 
	matrix. Will first make a [1*4]x[4x4]-type matrix product and after that bring the 
	result back to 3D.
	
	For more complete documentation search for "##homogeneous coordinates"...
*/

void TransformVector(oglv3d<GLfloat> &, const GLfloat *);

/**	This sets the current modelview-matrix equivalent to the location and orientation 
	of the object without making any persistent changes to the matrix stack state.
*/

void SetModelView(const ogl_obj_loc_data *);

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

/**	Object location data is stored here.

	Directions are similar to those in OpenGL:
	"zdir" -> positive direction is to the forward.
	"ydir" -> positive direction is to the upward.
	"xdir" -> positive direction is to the left.
	
	All vectors are supposed to be unit vectors !!!
	Only lights will use the fourth component !!!
*/

struct ogl_obj_loc_data
{
	GLfloat crd[4];
	oglv3d<GLfloat> zdir;
	oglv3d<GLfloat> ydir;
	
	int lock_count;
};

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

/**	The "##ogl_dummy_object" is a base class for many internally used objects (like cameras, 
	lights, clippers and transformers), and contains interfaces for transformations, 
	simple modifications and rendering.
	
	Some objects (like ribbons) are fixed so not all objects necessarily have object_location...
*/

class ogl_dummy_object
{
	protected:
	
	ogl_object_location * ol;
	int my_id_number;
	
	public:
	
	ogl_dummy_object(bool);
	ogl_dummy_object(const ogl_object_location &);
	virtual ~ogl_dummy_object(void);
	
	void SetModelView(void) const;
	
	const ogl_obj_loc_data * GetSafeLD(void) const;		// read access only.
	ogl_obj_loc_data * GetLD(void) const;			// read/write access.
	
	public:
	
	virtual const char * GetObjectName(void) = 0;
	
	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) = 0;
	virtual bool EndTransformation(void) = 0;
	
	virtual void Render(void) = 0;
};

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

// UNDER CONSTRUCTION!!!!! UNDER CONSTRUCTION!!!!! UNDER CONSTRUCTION!!!!!
// UNDER CONSTRUCTION!!!!! UNDER CONSTRUCTION!!!!! UNDER CONSTRUCTION!!!!!
// UNDER CONSTRUCTION!!!!! UNDER CONSTRUCTION!!!!! UNDER CONSTRUCTION!!!!!

//struct smart_client
//{
//	graphics_view * client;
//	void * custom_data;
//};
//	vector<smart_client> client_vector;

/**	The "##smart_object" is used to implement complex visualization objects (like colored 
	3D-planes and surfaces, and ribbon models of peptides/proteins).
	
	A "##smart_object" can respond to connectivity/geometry changes and can have other 
	customized properties. Clippers can be used to clip smart_objects (AND ONLY THOSE?????). 
	BAD NEWS: the clipper objects does not exist yet.
	
	"##new connectivity" means that some atoms/bonds have been added/removed.
	"##new geometry" means that some atom coordinates have been modified.
	
	THIS IS STILL A BIT UNDER CONSTRUCTION!!!
*/

class ogl_smart_object :
	public ogl_dummy_object
{
	private:
	
	list<ogl_camera *> cam_list;
	
	public:
	
	bool transparent;	// why public???
	
	public:
	
	ogl_smart_object(void);
	ogl_smart_object(const ogl_object_location &);
	virtual ~ogl_smart_object(void);
	
	void ConnectCamera(ogl_camera &);
	
	virtual void CameraEvent(const ogl_camera &) = 0;
	
/*##############################################*/
/*##############################################*/

//	virtual bool AddClient(some_view *, void *) = 0;
//	virtual bool RemoveClient(some_view *) = 0;
	
//	virtual void NewConnectivity(void) = 0;
//	virtual void NewGeometry(void) = 0;
};

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

/**	The "##ogl_object_location" is an abstract base class for all objects(???). It contains 
	information about the position and orientation of the object and is also able to write 
	that information into the OpenGL modelview matrix.
	
	Idea is to create derived classes that can have different (also dynamic) ways to 
	determine the location...
*/

class ogl_object_location
{
	protected:	// FC3 compiler does not accept this?
//	public:		// this is the obvious fix to the above...
	
	ogl_obj_loc_data * data;
	
friend const ogl_obj_loc_data * ogl_dummy_object::GetSafeLD(void) const;
friend ogl_obj_loc_data * ogl_dummy_object::GetLD(void) const;
	
	public:
	
	ogl_object_location(void);
	ogl_object_location(const ogl_object_location &);
	virtual ~ogl_object_location(void);
	
	void SetModelView(void) const;
	
	const ogl_obj_loc_data * GetSafeLD(void) const;
	
	virtual void UpdateLocation(void) const = 0;
	virtual ogl_object_location * MakeCopy(void) const = 0;
};

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

/// A simple static object location - seems to work, just use this...

class ogl_ol_static :
	public ogl_object_location
{
	protected:
	
// this is just an interface definition -> there is no relevant common data?!?!?
// this is just an interface definition -> there is no relevant common data?!?!?
// this is just an interface definition -> there is no relevant common data?!?!?

	public:
	
	ogl_ol_static(void);
	ogl_ol_static(const ogl_obj_loc_data *);
	~ogl_ol_static(void);
	
	void UpdateLocation(void) const;
	ogl_object_location * MakeCopy(void) const;
};

/**	A dynamic object location (UNDER CONSTRUCTION).
	
	The idea here is, that we could make objects that are automatically located using 
	some external data; for example we could have a camera or a light that is always 
	focused on a target, no matter how the target moves. We would have here pointers 
	to the target coordinates, and we would update the object location dynamically 
	using those...
*/

class ogl_ol_dynamic_l1 :
	public ogl_object_location
{
	private:
	
// bring the points and weights here?!?!?!?!?
// bring the points and weights here?!?!?!?!?
// bring the points and weights here?!?!?!?!?

	public:
	
	ogl_ol_dynamic_l1(void);
	~ogl_ol_dynamic_l1(void);
	
	void UpdateLocation(void) const;
	ogl_object_location * MakeCopy(void) const;
};

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

#endif	// OGL_OBJECTS_H

// eof
