// written by André Betz 
// http://www.andrebetz.de

#include <math.h>
#define PI	3.1415927

class Object
{
public:
	Object(unsigned long ulPoints,double* pdPoints);
	~Object();
	void Set(double dPosX,double dPosY,double dPosZ,
 			 double dPhiX,double dPhiY,double dPhiZ);
protected:
	unsigned long	m_ulPoints;
	double			m_dPosX;
	double			m_dPosY;
	double			m_dPosZ;
	double			m_dPhiX;
	double			m_dPhiY;
	double			m_dPhiZ;
	double*			m_pdPoints;
	double*			m_pdTempPoints;
	double*			m_pdCopyPoints;
	double			Grad2Bogen(double dGrad);
	double			MySin(double dGrad);
	double			Correct(double dGrad);
	void			Dreh(unsigned long ulPos);
	void			Transform(unsigned long ulPos);
	void			Project(unsigned long ulPos);
};

Object::Object(unsigned long ulPoints,double* pdPoints)
{
	unsigned long	ulCount;

	m_dPosX			= 0.0;
	m_dPosY			= 0.0;
	m_dPosZ			= 0.0;
	m_dPhiX			= 0.0;
	m_dPhiY			= 0.0;
	m_dPhiZ			= 0.0;
	m_ulPoints		= ulPoints;
	m_pdPoints		= pdPoints;
	m_pdCopyPoints	= new double[m_ulPoints*3];
	m_pdTempPoints	= new double[m_ulPoints*3];

	for(ulCount=0;ulCount<m_ulPoints;ulCount++)
	{
		m_pdCopyPoints[ulCount*3+0]	= m_pdPoints[ulCount*3+0];
		m_pdCopyPoints[ulCount*3+1]	= m_pdPoints[ulCount*3+1];
		m_pdCopyPoints[ulCount*3+2]	= m_pdPoints[ulCount*3+2];
	}
}

Object::~Object()
{
	delete m_pdCopyPoints; 
}

void Object::Set(double	dPosX,double dPosY,double dPosZ,
 				 double	dPhiX,double dPhiY,double dPhiZ)
{
	unsigned long	ulCount;

	m_dPosX	= dPosX;
	m_dPosY	= dPosY;
	m_dPosZ	= dPosZ;
	m_dPhiX	+= dPhiX;
	m_dPhiY	+= dPhiY;
	m_dPhiZ	+= dPhiZ;

	if(m_dPhiX>360.0)	m_dPhiX = Correct(m_dPhiX);
	if(m_dPhiY>360.0)	m_dPhiY = Correct(m_dPhiY);
	if(m_dPhiZ>360.0)	m_dPhiZ = Correct(m_dPhiZ);

	for(ulCount=0;ulCount<m_ulPoints;ulCount++)
	{
		Dreh(ulCount*3);
		Transform(ulCount*3);
		Project(ulCount*3);
	}
}

double Object::Grad2Bogen(double dGrad)
{
	double dBogen;
	dBogen = (PI * dGrad) / 180.0;
	return dBogen;
}

double Object::MySin(double dGrad)
{
	double			dSinus;
	double			dBogen;
	
	if(dGrad>=360.0)	dGrad = Correct(dGrad);
	if(dGrad==180.0)	return 0.0;
	dBogen = Grad2Bogen(dGrad);
	dSinus = sin(dBogen);

	return dSinus;
}

double Object::Correct(double dGrad)
{
	unsigned long	ulHelp;
	double			dCGrad;

	if(dGrad>360.0)
	{
		ulHelp	= (unsigned long)(dGrad / 360.0);
		dCGrad	= dGrad - 360.0 * ulHelp;
	}

	return dCGrad;
}

void Object::Dreh(unsigned long ulPos)
{
	double dSinPhiX;
	double dSinPhiY;
	double dSinPhiZ;
	double dCosPhiX;
	double dCosPhiY;
	double dCosPhiZ;

	dSinPhiX = MySin(m_dPhiX);
	dSinPhiY = MySin(m_dPhiY);
	dSinPhiZ = MySin(m_dPhiZ);
	dCosPhiX = MySin(m_dPhiX+90.0);
	dCosPhiY = MySin(m_dPhiY+90.0);
	dCosPhiZ = MySin(m_dPhiZ+90.0);

	m_pdTempPoints[ulPos+0] =	( dCosPhiX*dCosPhiZ - dSinPhiX*dCosPhiY*dSinPhiZ) * m_pdCopyPoints[ulPos+0] +
								            (-dCosPhiX*dSinPhiZ - dSinPhiX*dCosPhiY*dCosPhiZ) * m_pdCopyPoints[ulPos+1] +
								              dSinPhiX*dSinPhiY                               * m_pdCopyPoints[ulPos+2];

	m_pdTempPoints[ulPos+1] =	( dSinPhiX*dCosPhiZ + dCosPhiX*dCosPhiY*dSinPhiZ) * m_pdCopyPoints[ulPos+0] +
								            (-dSinPhiX*dSinPhiZ + dCosPhiX*dCosPhiY*dCosPhiZ) * m_pdCopyPoints[ulPos+1] -
								              dCosPhiX*dSinPhiY                               * m_pdCopyPoints[ulPos+2];

	m_pdTempPoints[ulPos+2] =	  dSinPhiY*dSinPhiZ                               * m_pdCopyPoints[ulPos+0] + 
								              dSinPhiY*dCosPhiZ                               * m_pdCopyPoints[ulPos+1] + 
								              dCosPhiY                                        * m_pdCopyPoints[ulPos+2];


}

void Object::Transform(unsigned long ulPos)
{
	m_pdPoints[ulPos+0] = m_pdTempPoints[ulPos+0] + m_dPosX;
	m_pdPoints[ulPos+1] = m_pdTempPoints[ulPos+1] + m_dPosY;
	m_pdPoints[ulPos+2] = m_pdTempPoints[ulPos+2] + m_dPosZ;
}

void Object::Project(unsigned long ulPos)
{
	double dDist = 10;

	if(m_pdPoints[ulPos+2]!=0.0)
	{
//		m_pdPoints[ulPos+0] = m_pdPoints[ulPos+0] * dDist / m_pdPoints[ulPos+2];
//		m_pdPoints[ulPos+1] = m_pdPoints[ulPos+1] * dDist / m_pdPoints[ulPos+2];
	}
}

#include <windows.h>
#define	MD	100.0
#define SI	24

unsigned long	wx		= 400;
unsigned long	wy		= 400;
unsigned long	zahl	= 0;

double Wuerfel[SI*3] = 
{
	-MD,-MD,-MD,	-MD,-MD, MD,
	-MD,-MD,-MD,	-MD, MD,-MD,
	-MD,-MD,-MD,	 MD,-MD,-MD,

	 MD, MD, MD,	 MD, MD,-MD,
	 MD, MD, MD,	 MD,-MD, MD,
	 MD, MD, MD,	-MD, MD, MD,

	-MD, MD,-MD,	 MD, MD,-MD,
	-MD, MD,-MD,	-MD, MD, MD,

	-MD,-MD, MD,	-MD, MD, MD,
	-MD,-MD, MD,	 MD,-MD, MD,

	 MD,-MD,-MD,	 MD, MD,-MD,
	 MD,-MD,-MD,	 MD,-MD, MD
};

Object xWuerfel(SI,Wuerfel);

int Show(HWND hwnd)
{
	HDC				hdcWindow;
	HBRUSH			brush;
	HRGN			hrgn;
	BOOL			t;
	double			px = 1.6;
	double			py = 1.7;
	double			pz = 1.8;
	unsigned long	count;

	hdcWindow = GetDC(hwnd);

	hrgn = CreateRectRgn(0,0,wx,wy);
	brush = CreateHatchBrush(HS_BDIAGONAL,0x00ffffff);
	t = FillRgn(hdcWindow,hrgn,brush);

	xWuerfel.Set(200,200,200,1.3,1.5,1.7);

	for(count=0;count<SI*3;count+=6)
	{
		MoveToEx(hdcWindow,(int)Wuerfel[count+0],(int)Wuerfel[count+1],NULL);
		LineTo(hdcWindow,(int)Wuerfel[count+3],(int)Wuerfel[count+4]);
	}

	ReleaseDC(hwnd,hdcWindow);

	return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
	switch(Message)
	{
		case WM_CLOSE:
			DestroyWindow(hwnd);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_TIMER:
			Show(hwnd);
			break;
 
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
   }
   return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	WNDCLASSEX		WndClass;
	HWND			hwnd;
	MSG				Msg;
	char			ClassName[] = "MyWindowClass";
	UINT			idTimer1	= 1;
	UINT			nTimerDelay = 1;

	WndClass.cbSize        = sizeof(WNDCLASSEX);
	WndClass.style         = 0;
	WndClass.lpfnWndProc   = WndProc;
	WndClass.cbClsExtra    = 0;
	WndClass.cbWndExtra    = 0;
	WndClass.hInstance     = hInstance;
	WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	WndClass.lpszMenuName  = NULL;
	WndClass.lpszClassName = ClassName;
	WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

	RegisterClassEx(&WndClass);
	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,ClassName,"Dreh  Betz99",WS_OVERLAPPEDWINDOW,
					CW_USEDEFAULT,CW_USEDEFAULT,wx,wy,NULL,NULL,hInstance,NULL);

	ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);

	SetTimer(hwnd,idTimer1,nTimerDelay,NULL);

	while(GetMessage(&Msg,NULL,0,0))
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}

	KillTimer(hwnd, idTimer1);
	
	return Msg.wParam;
}
 

