//=============================================================================
//
// Copyright 1998 by Captivation Digital Laboratories, Inc.
// All Rights Reserved.
//
//=============================================================================
//
// "KRAD" -- Kamui Rendering/Animation Demonstration
//
// This file declares scene management classes
//		SceneNode	- primarily tree management and virtual holders
//		SceneRoot	- owner of the tree; has main loops
//		SceneCamera	- the camera class is tightly meshed with SceneRoot
//
//=============================================================================
//-----------------------------------------------------------------------------
// $Revision: 1 $
// $NoKeywords: $
//=============================================================================

#ifndef _SCENE3D_H_
#define _SCENE3D_H_

#include "krad.h"
#include "kalgebra.h"

//============================================================================= FORWARD DECLARATIONS

class	SceneNode;
class	SceneRoot;
class	SceneCamera;

//============================================================================= ENUMERATIONS
typedef enum
{
	NODE_DEL_AUTO,
	NODE_DEL_MANUAL,
}	NODE_DELETE_STYLE;

typedef enum
{
	NODE_LIST_OPAQUE			= 0x01,
	NODE_LIST_OPAQUE_MODIFIER	= 0x02,
	NODE_LIST_TRANS				= 0x04,
	NODE_LIST_TRANS_MODIFIER	= 0x08,
}	NODE_LIST_BITS;

//============================================================================= DEFINITIONS
// bitfields and arrays are use to represent active cameras
//-----------------------------------------------------------------------------
#define	MAX_ACTIVE_CAMERAS	32

//=============================================================================
//============================================================================= CLASS SceneNode
//=============================================================================
// The SceneNode class is a simple tree implementation for managing
// the scene and it's components.
//
// Only basic tree manipulation functions are provided
//
//-----------------------------------------------------------------------------
// USAGE:
//
//	Nodes are created via the constructor. Importantly, the NODE_DELETE_STYLE
//		must be set correctlyJ: NODE_DEL_AUTO or NODE_DEL_MANUAL.
//
//		NODE_DEL_MANUAL can always be used. It implied that the code using the
//		node system will clean up the nodes.
//
//		NODE_DEL_AUTO can be used on nodes created with operator new. These
//		nodes will be deleted automatically when they expire, or when an
//		parent (of any degree) is deleted.
//
//	Node deletion occurs via the destructor; it occurs implicitly via the
//		delete operator.
//
//		Invoking destructors/delete will cause the ENTIRE BRANCH to be deleted.
//		For objects that have the NODE_DEL_AUTO style of deletion, their
//		destructors will be called recursively and automatically.
//
//		NODE_DEL_MANUAL children will be orphaned. They will have been detached
//		cleanly, but will not be a member of the full scene. They will need
//		to be deleted separately or reattached to the scene. The entire branch
//		will be preserved.
//
//		The entire tree can be cleared by destructing all the NODE_DEL_MANUAL
//		objects.
//
//-----------------------------------------------------------------------------

class SceneNode
{
private:
	int					mDelStyle;

	SceneNode*			mParent;

	SceneNode*			mNextSibling;
	SceneNode*			mPrevSibling;

	SceneNode*			mFirstChild;
	SceneNode*			mLastChild;

	float				mBoundingRadius;

	NODE_LIST_BITS		mListBits;

protected: // TEMP <-- NEED FUNCTIONS TO ACCESS
	kmatrix				mTransform;			// The XForm matrix of record -- converts to parent's space
	kmatrix				mToWorld;			// transform matrix to convert to world coord space
	uint32				mToWorldTimeStamp;	// aging optimization

public:
	SceneNode			(NODE_DELETE_STYLE ndel, SceneNode* parent);
	virtual ~SceneNode	();

	void				AttachToParent		(SceneNode* parent);
	void				DestroyChildren 	(void);
	void				Detach				(void);
	SceneNode*			DFNext				(void);

	void				SetBoundingRadius	(float val)				{	mBoundingRadius = val;	};
	float				GetBoundingRadius	(void)					{	return mBoundingRadius;	}

	void				SetListTypes		(NODE_LIST_BITS lbits)	{	mListBits = lbits;		};
	NODE_LIST_BITS		GetListTypes		(void)					{	return mListBits;		};

	bool				InFrustrum			(void)					{	return(true);			};

	virtual void		EvaluateState					(void) = 0;
	virtual void		TransformAndRegisterTristrips	(kmatrix* m, NODE_LIST_BITS lbits) = 0;

#if 0
	void ApplyRotX();
	void ApplyRotY();
	void ApplyRotZ();
	void ApplyRotXY();
	void ApplyRotXZ();
	void ApplyRotYX();
	void ApplyRotYZ();
	void ApplyRotZX();
	void ApplyRotZY();
	void ApplyRotXYZ();
	void ApplyRotXZY();
	void ApplyRotYXZ();
	void ApplyRotYZX();
	void ApplyRotZXY();
	void ApplyRotZYX();

	void ApplyScaleX();
	void ApplyScaleY();
	void ApplyScaleZ();
	void ApplyScaleXY();
	void ApplyScaleXZ();
	void ApplyScaleYZ();
	void ApplyScaleXYZ();

	void ApplyTransX();
	void ApplyTransY();
	void ApplyTransZ();
	void ApplyTransXY();
	void ApplyTransXZ();
	void ApplyTransYZ();
	void ApplyTransXYZ();

	void ApplyMatrix();

	void SetPosX()
	void SetPosY()
	void SetPosZ()
	void SetPosXY()
	void SetPosXZ()
	void SetPosYZ()
	void SetPosXYZ()

	// GetMatrix();
	// GetPos();
#endif

	//for the rendering loop
	friend class SceneRoot;
};

//=============================================================================
//============================================================================= STRUCT SceneNodeDatum
//=============================================================================
// This class is used to track rendering viability of scenenodes
// It's just a SceneNode* and a bitfield
//-----------------------------------------------------------------------------
struct SceneNodeDatum
{
public:
	SceneNode*	mNodePtr;
	uint32		mCameraBits;
};

//=============================================================================
//============================================================================= CLASS SceneRoot
//=============================================================================
// The SceneRoot is the owner of the scene tree. It is intended for the
// system to have only a single scene root alive at any time.
//
// The SceneRoot is used to manage the scene, get scene information, and
// to handle the primary rendering functions
//-----------------------------------------------------------------------------
class SceneRoot : public SceneNode
{
private:
	SceneNodeDatum*	mListOpaque;
	SceneNodeDatum*	mListOpaqueMod;
	SceneNodeDatum*	mListTrans;
	SceneNodeDatum*	mListTransMod;
	uint32			mListCount;
	SceneCamera*	mActiveCameras[MAX_ACTIVE_CAMERAS];

private:
	uint32	ValidateCameraList (void);
	void	ValidateNodeLists (void);

	// Camera List
public:
			SceneRoot				(NODE_DELETE_STYLE	ndel);
	virtual	~SceneRoot				();
	void	ActivatePrimaryCamera	(SceneCamera& camera);
	void	ActivateCamera			(SceneCamera& camera);
	void	DeactivateCamera		(SceneCamera& camera);
	uint32	GetNodeCount			(void);

	bool	EvaluateAndRender		(void);

	// -- REQUIRED VIRTUALS --
	void	EvaluateState					(void)							{			};
	void	TransformAndRegisterTristrips	(kmatrix* m, NODE_LIST_BITS lbits) { m; lbits;	};

};

//=============================================================================
//============================================================================= CLASS SceneCamera
//=============================================================================
// There can be many cameras in a scene.
//
// An "Active" camera is one that performes rendering within its viewspace.
// There is a hard limit of 32 active cameras.
//
// The "Primary" camera is the camera that renders the ultimate frame
// buffer. There must be one Primary camera -- no more, no less.
//
// The camera activation routines here and in SceneRoot are identical
//-----------------------------------------------------------------------------

class SceneCamera : public SceneNode
{
private:
	bool	mActive;
	kmatrix	mToScreen;
	float	mCenterX;			// screen offset, FOV height
	float	mCenterY;
	float	mFOV;				// field-of-view, in degrees
	float	mDepth;				// depth from camera point to viewplane
	kmatrix	mScreenProjection;	// intermediate result
	kmatrix	mFromWorld;			// inverse of mToWorld

public:
			SceneCamera			(NODE_DELETE_STYLE	ndel, SceneNode* parent);
	virtual	~SceneCamera		();
	void	Activate			(void);
	void	ActivateAsPrimary	(void);
	void	Deactivate			(void);
	bool&	IsActive			(void)			{ 	return(mActive);	}

	float	GetFOV				(void)			{ 	return(mFOV);	}
	void	SetFOV				(float newfov);

	// -- REQUIRED VIRTUALS --
	void	EvaluateState					(void);
	void	TransformAndRegisterTristrips	(kmatrix* m, NODE_LIST_BITS lbits) { m; lbits;	};

	//for the rendering loop
	friend class SceneRoot;
};

//=============================================================================
//=============================================================================
//=============================================================================

#endif  // Headerfile Guard

//=============================================================================	END-OF-INCLUDE








//	//=============================================================================
//	//============================================================================= CLASS RenderContext
//	//=============================================================================
//
//	class ViewContext
//	{
//	//		ActiveElements		// array of pointers: numelements+1
//	//		InactiveElements	// [0..n) are active
//								// (n..numelements] are inactive.
//	//		RenderTarget
//	//		metrics about render (eg: size)
//
//	};
//
//	//=============================================================================
//	//============================================================================= CLASS SceneCamera
//	//=============================================================================
//
//	//	class KRenderCamera : class KRenderNode
//	//		KRenderContext
//	//		location	// specific, or mapped to matrix entries
//	//		orientation info
//	//		focal length/ field of view
//
//	//=============================================================================
//	//============================================================================= CLASS SceneTargetCamera
//	//=============================================================================
//	//	class KRenderTargetedCamera : class KRenderCamera
//	//		KRenderNode*	target
//
//
//	//=============================================================================
//	//============================================================================= CLASS SceneSprite
//	//=============================================================================
//	//	class KRenderSprite : class KRenderNode
//
//	//=============================================================================
//	//============================================================================= CLASS SceneText
//	//=============================================================================
//	//	class KRenderText : class KRenderSprite
//
//	//=============================================================================
//	//============================================================================= CLASS SceneMesh
//	//=============================================================================
//	//	class KRenderMesh : class KRenderNode
//	//		Points array	// x,y,z
//	//		Vertices array
//	//		Strips
//	//		Texture Reference
//	//		Animation
//	//		BoundingRadius
//
//	//=============================================================================
//	//============================================================================= CLASS SceneNodeInstance
//	//=============================================================================
//
//	// has own trans matrix -- refers to other node
//	// careful about cyclic trees
