// 2011 апрель 30 23:59:59
// рассматриваю предложения на переезд/снять комнату или приютите кто-нибудь бедного поросёночка :(
/* Sex Vodka Beer and TETRIS! 
первоначальная задумка - шутеро-тетрис под музычку Doom II OST - Map 01,15 - Running from Evil с бензопилой и огнестрелом по кружкам-бутылочкам. (FAILED)
Конкретная идея под конкурс стукнула в тот момент, когда захотелось запротестовать против пунктов в голосовалке из-за того, что я не употребляю).
Cначала тут была перекрашенная копи-паста тетриса Эльминго(Lyutov Sergey) www.irrlicht.ru  Art\prototype2.png - но лучше совсем ничего, чем чужое.
чужое полностью воровать совесть не позволяет - свое ...(((

кто-то с хабра: Я три летних месяца работал грузчиком в мувинговой компании под Нью-Йорком, шутки шутками, но тетрис я вспоминал каждый день. Я удивлён, что создатель алгоритма тетриса работал в Вычислительном Центре РАН,
а не грузчиком на подхвате в каком-нибудь магазине.

Картонажной фабрике требуются рабочие:
1. Грузчики (Тетрис, Сокобан)
2. Диспетчер (Sim City, Railroad Tycoon)
3. Водители (опыт GTA нежелателен)



Когда-то, давно, мы с коллегами провели тест на тетрисе (гениальная игрушка!).
Тот, кто старался оставить минимальное число линий внизу, оказывался хорошим сотрудником.
Тот, кто старался закрыть линии сверху, отставляя дырки снизу, работал так же, поверхностно.
А когда появились первые думеры, началась совсем другая статистика…
Если с утра ходит на автопилоте и отвечает нечленораздельно, значить думер…
А куда-то потом они все подевались…

*/
//***Image****      .---.         .-"-.      ********************
//*  Copied  *     /   ._.       / ґ ` \     *                  * 
//*  from    *     \_  (__\      \_°v°_/     *                  *
//*  Humus   *     //   \\       //   \\     *                  *
//* -------- *    ((     ))     ((     ))    * ---------------- *
//*          ****--""---""-------""---""--****\ *\

// ********************План проекта:********************
/*
  луч на столкновения--	(код под чтение - shield effect in irrlicht - 2 черепашки)
 менюшка winAPI--	через triangle selection по raytrace лучику (ибо каждую кнопочку через createwindow - меня выворачивает)
 менеджер состояний--
http://gamedevgeek.com/tutorials/managing-game-states-in-c/ - менеджер состояний SDL (эх, и что же мне тогда в 2000м не понравилось в SDL ???)
http://www.codeproject.com/KB/architecture/StatePattern3/StatePattern3_demo.zip	 менеджер состояний MFC	(требуется регистрация на сайте)
http://www.irrlicht.ru/wiki/Irrlicht/CodeSnippets-logic-1 
 частицы (огонь)--
 частицы (взрыв)--
 текст из текстур--
 куча хлама с hackchina.com
 камера на квантернионах--
 глупый шутливый микс голосов героев диаблы1  http://www.apsa.cz/rvalek/diablo/files/download/3some.zip 1,38 Мб
 таймер НЕ WM_TIMER|timeGetTime|GetTickCount--
 x86 PCs have a nice hardware clock that runs at 1193180hz (1.13198 MHz), microsecond resolution.

точности GetTickCount() слишком мало и нужно использовать например QueryPerfomanceCounter
Скорость камеры умноженная на дельту времени (разница между кадрами) это правильный путь. 
Есть такой вопрос: а если камеру не шевелить, а будут шевелиться только объекты на экране, они дергаются? 
И еще одна поправка: время кадра нужно засекать вместе со всеми другими действиями, а не только с момента начала рендеринга.

>Насчет QueryPerfomanceCounter() не надо парить. Я вначале как раз ее и использовал. 
>Она СЛИШКОМ чувствительна. От этого все дергается еще сильнее.=(
Дергаться может от потери точности расчета дельты, но никак не от ее избыточности

Ну смотри. У тебя есть счетчик игрового времени, который ты меряешь через QPC. Надежно это можно делать только из одного треда, который прибит к конкретному ядру через SetThreadAffinity.
Если померять время потребуется другому треду - ему нельзя его мерять самому, он должен его спрашивать у главного. Если это время игровое (длительность кадра и т.д.), главный тред может его записывать каждый кадр в shared variable, до которой синхронизованный доступ. Это небольшая проблема.
Противно - когда второй тред хочет получить натурально timestamp. Сам он его взять не может, надо каким-то образом "обратиться" к первому. Тут уже видимо надо вообще выделять отдельный тред, который большую часть времени спит и только отвечает на запросы о timestamp.
решение - заставить юзверей обновить драйвер cpu| Играм в диспетчере в меню Set Affinity ставишь один проц. или прям в коде через SetThreadAffinityMask

Microsoft не рекомендует использовать QPC для таймера. timeBeginPeriod/timeEndPeriod и timeGetTime с верхним ограничением FPS. Подробнее - где-то в середине http://www.gamedev.ru/community/gamedev_lecture/articles/game_orhetecture

All I want is the damn time of day in milliseconds. Is this too much to ask?
Yes, it's tragic: no single call does everything you want. If you want the actual time of day, you have to use GetSystemTime(). Хотя эта функция returns a field which is milliseconds, it actually has a resolution of about 50ms.
You can also use a multimedia function called timeGetTime() которая действительно return an accurate time in milliseconds, но её значение - это время прошедшее с момента загрузки системы вместо the time of day.
If you need accurate time for the purposes of profiling, you can use QueryPerformanceCounter() which gives extremely accurate timings in a completely arbitrary units that must be converted to meaningful units with QueryPerformanceFrequency().

void main() {
   __int64 start, end, freq;

   QueryPerformanceCounter((LARGE_INTEGER*)&start);
   Sleep (1000);
   QueryPerformanceCounter((LARGE_INTEGER*)&end);

   QueryPerformanceFrequency((LARGE_INTEGER*)&freq);

   double ms = (double)(end - start) * 1000.0 / (double)freq;
   printf("%f\n",ms);
   while(1);
}


QueryUnbiasedInterruptTime - this function is available starting with Windows 7 and Windows Server 2008 R2.
BOOL QueryUnbiasedInterruptTime(  __out  PULONGLONG UnbiasedTime);  // UnbiasedTime [out]  Points to a variable to receive the unbiased interrupt-time count in system time units of 100 nanoseconds.
The interrupt-time count retrieved by the QueryUnbiasedInterruptTime function reflects only the time that the system is in the working state.
Therefore, the interrupt-time count is not "biased" by time the system spends in sleep or hibernation. 
The system uses biased interrupt time for some operations, such as ensuring that relative timers that would have expired during sleep expire immediately upon waking.
*/


#define STRICT
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers:. Non-MFC applications can define WIN32_LEAN_AND_MEAN and applicable NOservice definitions to reduce build times.
#define VC_LEANMEAN				//To speed the build proces
#define NOMINMAX

#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>		// timeGetTime
#include <bass.h>	// 2.4
#include <d3d9.h>	// DX9SDK 2006 april
#include <d3dx9.h>
#include <d3dx9core.h>    //  ID3DXFont

#include <stdio.h>  //  printf swprintf
//#include <stdlib.h>
#include <math.h>
#include <string.h>	//  strlen const char - не совместим с WCHAR - wcslen
#include <tchar.h>	//  _Т(текст) +работы со строками в кодировке юникод		You cannot cast a char* to LPWSTR. If you are using an Unicode build, use a TCHAR buffer
//#include <wtypes.h>
#include <time.h>

#pragma comment (lib,"d3d9.lib")	
#pragma comment (lib,"d3dx9.lib")	
#pragma comment(lib,"winmm.lib")	// <mmsystem.h>
#pragma comment(lib,"bass.lib")
#pragma comment(lib,"dinput8.lib")
#pragma comment(lib,"dxguid.lib")



//TimerCounter.h
//TimeCounter timer;
//timer.Start();
//...................
//timer.Stop();
//std::cout << timer;


/*важно после delete pPointer; делать pPointer = NULL; или пишем {sProcess p;} и получаем удаление нулл-поинтера, супер ^|')*/
#define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }	// For release something
#define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }	// For delete something
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }	// For delete array

//-=------Прототипы---------
//void    CALLBACK OnLostDevice();
//HRESULT CALLBACK OnResetDevice();
//void GetBulletColObjTransform(btRigidBody* body, D3DXMATRIX &World);
//void Updatedt(void);
//void InitPhysics(void);
//void DeleteCollisionShape(btCollisionShape* shape);
void Render(void);
void CleanAll(void);
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);   // Объявление WindowProc
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
//double ftime();

//------------------------------------интерфейсы DirectX------------------------------------
IDirect3D9			*pD3D = NULL;			// указатель на объект Direct3d9
IDirect3DDevice9	*pDevice = NULL;		// указатель на устройство Direct3d9
ID3DXFont			*pFont  = NULL;			// Указатель на интерфейс ID3DXFont
ID3DXFont			*pFont_Small = NULL;	// Указатель на ID3DXFont для маленького текста

ID3DXMesh*           g_pMesh3DText = NULL;	
D3DMATERIAL9 mtrl;
//IDirect3DVertexBuffer9 * pVB;
//IDirect3DIndexBuffer9  * pIB;

//IDirect3DVertexBuffer9 *g_pBillboardVB	= NULL;
//IDirect3DVertexBuffer9 *g_pFloorVB		= NULL;
//LPDIRECT3DTEXTURE9 Texture1 = NULL;
//LPDIRECT3DTEXTURE9 Texture2 = NULL;

/*
ID3DXMesh* PlatformMesh;
ID3DXMesh* BoxMesh;
ID3DXMesh* SphereMesh;
ID3DXMesh* CylinderMesh;
ID3DXMesh* BoxLeftMesh;
ID3DXMesh* BoxRightMesh;
*/



//-------------------------------------------глобальные-------------------------------------------
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
BOOL running=true;
HWND hwnd=NULL;             // globally track main window
HINSTANCE hInstance      = NULL; // globally track hinstance
WNDCLASSEX wc;
HANDLE Mutex; // блокировка копий 

int width =GetSystemMetrics(SM_CXSCREEN);	// размер экрана по умолчанию
int height=GetSystemMetrics(SM_CYSCREEN);
int ScreenWidth;		// размер экрана в зависимости от режима - уточняется в создании окна
int ScreenHeight;
int pos_x=0;	// уточняется при создании/пересоздании окна
int pos_y=0;
WCHAR buffer[128];          // массив символов для текстовой строки "buffer"
WCHAR buffer_pos[128];
WCHAR buffer_pos_now[128];
WCHAR buffer_size[128];
WCHAR buffer_param[128];
WCHAR buffer_param2[128];

enum { ID_BUTTON1,ID_BUTTON2,ID_BUTTON3,ID_BUTTON4};
HWND button1;
HWND button2;
HWND button3;
HWND button4;


D3DPRESENT_PARAMETERS d3dpp;
bool fullscreen=false;		// переключатель режима окна – (вкл. fullscreen)
bool VsyncSwitcher=true;	// переключатель vsync – (выкл. Vsync)
UINT vsync=0;				// хранит значение d3dpp.PresentationInterval



#define MY_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
struct SMyVertex
{
  D3DXVECTOR3 pos;		 
  D3DXVECTOR3 norm;		// Нормаль
  FLOAT tu, tv;			// Текстурные координаы
};
LPDIRECT3DTEXTURE9	g_pTexture		= NULL;		// указатель на текстуру.
LPDIRECT3DVERTEXBUFFER9 g_pVB		= NULL;		// вешинный буфер.


//DWORD str_start;	// для музыки
DWORD mus_start;



// свои научные изыскания -  потом когда-нибудь
//int Game_State=0;
/*enum  Game_State  
{
	intro,
	intro2,
	menu,
	main_process,
	options,
};*/

  ////Константы, для определения текущего состояния программы
  //gsMenu=0;  //Мы находимся в меню
  //gsGame=1;  //Мы находимся в процессе игры
  //gsGameOver=2; //Мы смотрим на то, как нам говорят, что мы проиграли
  //GameState:Longint; 
// Procedure StartGame; 
//




RECT rc1={ width-80, 0, 0, 0 };
RECT rc2={1, 1, 0, 0};			/* для надписи: FPS*/ RECT rc21={100, 1, 0, 0};	RECT rc22={340, 1, 0, 0};		
RECT rc3={1, 21, 0, 0};			// для надписи <ESC>
RECT rc4={1, 41, 0, 0};			// для надписи <F1>
RECT rc5={100, 161, 0, 0};			// для надписи <F2>
RECT rc6={1, 81, 0, 0};			// для надписи <F3>
RECT rc7 ={0, 101, 0, 0};		// для надписи <F4> - text
RECT rc8 ={(width/2-100), 0, 0, 0};


//#define FVF3D (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE)
#define FVF3D (D3DFVF_XYZ | D3DFVF_TEX1)
struct s3DVertex
{
   FLOAT x, y, z;
   FLOAT u, v;
//   DWORD color;
};

float FPS, CurrentTime, LastTime  = 0.0f;// переменные для счетчика
double dt= 0.0f; // DeltaTime

// Таймер
void Updatedt()
{
	FPS++;
	// timeBeginPeriod(UINT uPeriod); - // тут потом допишу - чтоб точность timeGetTime поставить в 1 мс
	// timeEndPeriod(UINT uPeriod);
	
	CurrentTime= (float)timeGetTime() * 0.001f; // тормозная вещь по времени выполнения - 8 мс
	dt=CurrentTime - LastTime;
	//если прошла секунда, то вывести число FPS
   if( dt >= 1.0f)
      {
          LastTime = CurrentTime;
          swprintf(buffer, L"%ix%i %4.2f", ScreenWidth,ScreenHeight,FPS);
          FPS = 0;
      }
}

//-----------------------------------------------------------------------------
// Name: CreateD3DXTextMesh()
//-----------------------------------------------------------------------------
HRESULT CreateD3DXTextMesh( IDirect3DDevice9* pDevice,
                            LPD3DXMESH* ppMesh,
                            TCHAR* pstrFont, DWORD dwSize,
                            BOOL bBold, BOOL bItalic )
{
    HRESULT hr;
    LPD3DXMESH pMeshNew = NULL;
    HDC hdc = CreateCompatibleDC( NULL );
    if( hdc == NULL )
        return E_OUTOFMEMORY;
    INT nHeight = -MulDiv( dwSize, GetDeviceCaps( hdc, LOGPIXELSY ), 72 );
    HFONT hFont;
    HFONT hFontOld;

    hFont = CreateFont( nHeight, 0, 0, 0, bBold ? FW_BOLD : FW_NORMAL, bItalic, FALSE, FALSE, DEFAULT_CHARSET,
                        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
                        pstrFont );

    hFontOld = ( HFONT )SelectObject( hdc, hFont );

    hr = D3DXCreateText( pDevice, hdc, L"This is calling D3DXCreateText",
                         0.001f, 0.4f, &pMeshNew, NULL, NULL );

    SelectObject( hdc, hFontOld );
    DeleteObject( hFont );
    DeleteDC( hdc );

    if( SUCCEEDED( hr ) )
        *ppMesh = pMeshNew;

    return hr;
}
// ----------------------------------------------------
// Функция MakeSuperFont()
// Создает шрифт для вывода текста на основе ID3DXFont
// (когда-нибудь переделать на шрифт из текстуры)
//----------------------------------------------------
void MakeSuperFont( INT FontHeight, UINT FontWeight, LPCWSTR pFaceName, ID3DXFont **ppd3dxFont)
{
    ID3DXFont *pFontNew = NULL;    // временный шрифт (указатель на указатель)
      D3DXCreateFontW(pDevice,        // D3D device
                   FontHeight,        // Height - высота символа
                   0,            // Width - длина сивола
                   FontWeight,        // Weight - ширина
                   0,            // the number of MipLevels
                   FALSE,        // Italic – курсив
                   DEFAULT_CHARSET,    // CharSet
                   OUT_TT_ONLY_PRECIS,    // OutputPrecision (TrueType)
                   DEFAULT_QUALITY,    // Quality
                   DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily
                   pFaceName,        // наименование шрифта. Например, "Arial" - изменение LPCSTR-LPCWSTR смотри в объяве MakeSuperFont
				   &pFontNew);        // ppFont - указатель на используемый интерфейс ID3DXFont
    *ppd3dxFont = pFontNew;
}

//bool InitObjects()
//{
//
// //  // Triangle data for its size and color.
//	//Vertex Triangle_Data[3] =
// //  {
//	//	{-0.1f, -0.1f, 0.0f, D3DCOLOR_XRGB(200,0,0)},
// //     {0.1f, -0.1f, 0.0f, D3DCOLOR_XRGB(200,0,0)},
//	//   {0.0f, 0.1f, 0.0f, D3DCOLOR_XRGB(0,210,0)}
//	//};
//
// //  // Create the vertex buffer that will hold the triangle.
//	//if(FAILED(pDevice->CreateVertexBuffer(sizeof(Triangle_Data),
// //                                           0, D3DFVF_D3DVertex,
// //                                           D3DPOOL_DEFAULT, &Object_Buffer, NULL)))
// //     {
// //        return false;
// //     }
//	//
// //  Vertex* Vertices;	// Pointer to the buffer.
//
// //  // Lock the buffer we can write to it.
// //  if(FAILED(Object_Buffer->Lock(0, sizeof(Triangle_Data), (void**)&Vertices, 0)))      return false;
// //  memcpy(Vertices, Triangle_Data, sizeof(Triangle_Data));
// //  Object_Buffer->Unlock();
//   // Create the ground.
// //  Vertex Floor_Data[] =
// //  {
// //     {-4.0f, -0.2f,-4.0f, D3DCOLOR_XRGB(255,255,255), 0.0f, 1.0f},
//	//   {-4.0f, -0.2f, 4.0f, D3DCOLOR_XRGB(255,255,255), 0.0f, 0.0f},
//	//   { 4.0f, -0.2f,-4.0f, D3DCOLOR_XRGB(255,255,255), 1.0f, 1.0f},
//	//   { 4.0f, -0.2f, 4.0f, D3DCOLOR_XRGB(255,255,255), 1.0f, 0.0f}
//	//};
//
//
// //  // Create the vertex buffer that will hold the triangle.
//	//if(FAILED(pDevice->CreateVertexBuffer(sizeof(Floor_Data),
// //                                           0, D3DFVF_D3DVertex,
// //                                           D3DPOOL_DEFAULT, &lable_1, NULL)))
// //     {         return false;       }
//	//   
//	//Vertex* Vertices;	// Pointer to the buffer.
//	//if(FAILED(lable_1->Lock(0, sizeof(Floor_Data), (void**)&Vertices, 0)))	    return false;	// Lock the buffer we can write to it
//	//memcpy(Vertices, Floor_Data, sizeof(Floor_Data));
//	//lable_1->Unlock();
//	//if(D3DXCreateTextureFromFile(pDevice, L"contest3.png", &Texture1) != D3D_OK) return false;
//	BYTE *Ptr;
//  s3DVertex BillboardVerts[4] = {
//      { -42.0f, 80.0f, 0.0f, 0.0f, 0.0f },
//      {  40.0f, 80.0f, 0.0f, 1.0f, 0.0f },
//      { -40.0f,  0.0f, 0.0f, 0.0f, 1.0f },
//      {  40.0f,  0.0f, 0.0f, 1.0f, 1.0f }
//    };
//
//  s3DVertex FloorVerts[4] = {
//      { -100.0f, 0.0f,  100.0f, 0.0f, 0.0f },
//      {  100.0f, 0.0f,  100.0f, 1.0f, 0.0f },
//      { -100.0f, 0.0f, -100.0f, 0.0f, 1.0f },
//      {  100.0f, 0.0f, -100.0f, 1.0f, 1.0f }
//    };
//
//  // Create vertex buffers and stuff in data
//  // Billboard
//  if(FAILED(pDevice->CreateVertexBuffer(                 \
//            sizeof(BillboardVerts), 0, FVF3D,                 \
//            D3DPOOL_DEFAULT, &g_pBillboardVB, NULL)))
//    return FALSE;
//  if(FAILED(g_pBillboardVB->Lock(0,0, (void**)&Ptr, 0)))
//    return FALSE;
//  memcpy(Ptr, BillboardVerts, sizeof(BillboardVerts));
//  g_pBillboardVB->Unlock();
//
//   // Floor
//  if(FAILED(pDevice->CreateVertexBuffer(                 \
//            sizeof(FloorVerts), 0, FVF3D,                     \
//            D3DPOOL_DEFAULT, &g_pFloorVB, NULL)))
//    return FALSE;
//  if(FAILED(g_pFloorVB->Lock(0,0, (void**)&Ptr, 0)))
//    return FALSE;
//  memcpy(Ptr, FloorVerts, sizeof(FloorVerts));
//  g_pFloorVB->Unlock();
//
//  // Get textures 
//  D3DXCreateTextureFromFile(pDevice, L"Art/contest3-1.png", &Texture2);
//  D3DXCreateTextureFromFileEx(pDevice, L"Art/contest3.png", 
//    D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A1R5G5B5, 
//    D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE, D3DX_FILTER_TRIANGLE,
//    D3DCOLOR_RGBA(0,0,0,255), NULL, NULL, &Texture1);
//
//	return true;
//}

//-----------------------
// Инициализация Direct3D
//-----------------------
bool InitDirect3D(HWND hwnd)
{
    HRESULT hr=0;
    pD3D = Direct3DCreate9(D3D_SDK_VERSION);
    if( !pD3D)
    {
        if(pD3D != NULL )pD3D->Release();
        ::MessageBox(0, L"Direct3DCreate9(D3D_SDK_VERSION) - Failed", 0, 0);
        return false;
    }

    D3DDISPLAYMODE Display;
    if(FAILED(pD3D -> GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Display)))
    {
        ::MessageBox(0, L"GetAdapterDisplayMode - Failed", 0, 0);
        return false;
    }

    D3DCAPS9 caps;
    if(FAILED(pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps) ) )
    {
        if( pD3D != NULL )pD3D->Release();
        ::MessageBox(0, L"GetDeviceCaps() - Failed", 0, 0);
        return false;
    }

    int vp = 0;
    if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
        vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    if(VsyncSwitcher)
    {
        vsync = D3DPRESENT_INTERVAL_DEFAULT;    // переключатель  вкл. vsync
    }
    else
    {
        vsync = D3DPRESENT_INTERVAL_IMMEDIATE;    // переключатель  выкл. vsync
    }

	memset(&d3dpp,0,sizeof(D3DPRESENT_PARAMETERS));
    d3dpp.Windowed				= !fullscreen;    // переключатель режима экрана
    d3dpp.BackBufferFormat		= Display.Format;
    d3dpp.EnableAutoDepthStencil= true;
    d3dpp.AutoDepthStencilFormat= D3DFMT_D24S8; // быстрее, чем D3DFMT_D16 на 0-20%
    d3dpp.BackBufferWidth		= ScreenWidth;
    d3dpp.BackBufferHeight		= ScreenHeight;
    d3dpp.BackBufferCount		= 1;
    if(fullscreen)
    {
        d3dpp.FullScreen_RefreshRateInHz=Display.RefreshRate;
        d3dpp.SwapEffect        = D3DSWAPEFFECT_FLIP;
    }
    else
    {
        d3dpp.FullScreen_RefreshRateInHz=0;
        d3dpp.SwapEffect        = D3DSWAPEFFECT_DISCARD;
    }

    d3dpp.PresentationInterval     = vsync;     // переключатель vsync

    hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT,
        D3DDEVTYPE_HAL, hwnd,
        vp,
        &d3dpp, &pDevice );
    if(FAILED(hr))
    {
        // попытаться ещё раз, используя 16-битный буфер глубины
        d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
        
        hr = pD3D->CreateDevice(
            D3DADAPTER_DEFAULT,
            D3DDEVTYPE_HAL,
            hwnd,
            vp,
            &d3dpp,
            &pDevice);

        if(FAILED(hr))
        {
            pD3D->Release();
            ::MessageBox(0, L"CreateDevice() - FAILED", 0, 0);
            return false;
        }
    }

	
	
	pDevice->CreateVertexBuffer( 6*sizeof(SMyVertex),	// size of vertex buffer in bytes
								0,						// Usage - 0 is hardware vertex processing
								MY_VERTEX_FORMAT,		// FVF flags - this case is untransformed vertex and 1 texture coords
								D3DPOOL_MANAGED,		// Memory pool is managed by the device
								&g_pVB,					// the vertex buffer !NULL is successful
								0);						// Reserved
	
  // Заполняем вершинный буфер. Для каждой вершины устанавливаем текстурные
	// координаты (tu, tv), которые лежат в интервале от 0.0 до 1.0
	SMyVertex* vertices;
   g_pVB->Lock( 0, 0, (void**)&vertices, 0 );
   // memcpy ???
	vertices[0].pos = D3DXVECTOR3(-1.0, 1.0, 0.0);
	vertices[0].norm = D3DXVECTOR3(0.0, 0.0, -1.0);
	vertices[0].tu = 0.0f;
	vertices[0].tv = 0.0f;
	
	vertices[1].pos = D3DXVECTOR3(1.0, 1.0, 0.0);
	vertices[1].norm = D3DXVECTOR3(0.0, 0.0, -1.0);	
	vertices[1].tu = 1.0f;
	vertices[1].tv = 0.0f;
	
	vertices[2].pos = D3DXVECTOR3(-1.0, -1.0, 0.0);
	vertices[2].norm = D3DXVECTOR3(0.0, 0.0, -1.0);	
	vertices[2].tu = 0.0f;
	vertices[2].tv = 1.0f;

	vertices[3].pos = D3DXVECTOR3(-1.0, -1.0, 0.0);
	vertices[3].norm = D3DXVECTOR3(0.0, 0.0, -1.0);	
	vertices[3].tu = 0.0f;
	vertices[3].tv = 1.0f;	
	
	vertices[4].pos = D3DXVECTOR3(1.0, 1.0, 0.0);
	vertices[4].norm = D3DXVECTOR3(0.0, 0.0, -1.0);	
	vertices[4].tu = 1.0f;
	vertices[4].tv = 0.0f;

	vertices[5].pos = D3DXVECTOR3(1, -1.0, 0.0);
	vertices[5].norm = D3DXVECTOR3(0.0, 0.0, -1.0);	
	vertices[5].tu = 1.0f;
	vertices[5].tv = 1.0f;
	g_pVB->Unlock();
	D3DXCreateTextureFromFile(pDevice, (L"Art/contest3.png"), &g_pTexture);
	pDevice->SetTexture(0, g_pTexture);


    pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );// Отключаем отсечение
   // pDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );    // Окружающие освещенние
    //pDevice->SetRenderState (D3DRS_ZENABLE, D3DZB_TRUE);    // Включаем Z буфер
	pDevice->SetRenderState (D3DRS_ZENABLE, D3DZB_FALSE);    // Выключаем Z буфер (для 2д графики)
    pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);			// освещение выкл., перед включением - настройте материалы!
	pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
	pDevice->SetRenderState(D3DRS_ALPHAREF, 0x01);
	pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);

	//pDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
	//pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
	//pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
	//pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );

	pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DX_FILTER_TRIANGLE);
	pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DX_FILTER_TRIANGLE);
	pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DX_FILTER_TRIANGLE);
	pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
    pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
	

    // Создание текста
    MakeSuperFont(90, FW_BOLD, L"Times New Roman", &pFont);
    MakeSuperFont(15, FW_MEDIUM, L"Arial", &pFont_Small);

	// Свет
//	pDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
    pDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( 0.2f, 0.2f, 0.2f, 1.0f ) );
	D3DLIGHT9 light0; 	ZeroMemory( &light0, sizeof(D3DLIGHT9) );
	light0.Type = D3DLIGHT_DIRECTIONAL;
	light0.Direction = D3DXVECTOR3(0.5f, -0.8f, 0.7f);
	light0.Diffuse.r = 1.0f;
	light0.Diffuse.g = 1.0f;
	light0.Diffuse.b = 1.0f;
	light0.Diffuse.a = 1.0f;
	pDevice->SetLight(0, &light0);
	pDevice->LightEnable(0, true);

		// Материал
	D3DMATERIAL9 mtrl;
	ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
	mtrl.Diffuse.r = 1.0f;
	mtrl.Diffuse.g = 1.0f;
	mtrl.Diffuse.b = 1.0f;
	mtrl.Diffuse.a = 1.0f;
	mtrl.Ambient.r = 1.0f;
	mtrl.Ambient.g = 1.0f;
	mtrl.Ambient.b = 1.0f;
	mtrl.Ambient.a = 1.0f;
	pDevice->SetMaterial(&mtrl);

	D3DXMATRIX matWorld;
	D3DXMatrixRotationY(&matWorld, 0);
	pDevice->SetTransform(D3DTS_WORLD, &matWorld);
 	
 	
	D3DXMATRIX matView;
	D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f, -2.4f),
								 &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
								 &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
								 
	pDevice->SetTransform(D3DTS_VIEW, &matView);
 	
	

	D3DXMATRIX matProj;
	D3DXMatrixPerspectiveFovLH(&matProj,D3DXToRadian( 45.0f ),ScreenWidth/ScreenHeight, 1.0f, 100.0f );
	pDevice->SetTransform(D3DTS_PROJECTION, &matProj);
 	


    return true;
}

//--------------
// Созданиe окна
// вся инициализация здесь, т.к. для идеи пересоздания окна
//--------------
bool MakeSuperWindow(bool fullscreen)
{
	HWND	   main_window_handle;	 // generic window handle
	
    if(hInstance == NULL) hInstance=(HINSTANCE)GetModuleHandle(NULL);

	Mutex = CreateMutex(NULL, FALSE, L"теломераза"); 
	if (GetLastError() == ERROR_ALREADY_EXISTS)
	{
		PostQuitMessage(0); // выход, т.к. экземпляр этого приложения уже запущен 
	}
	
	DWORD        dwExStyle;        // Window Extended Style
	DWORD        dwStyle;        // Window Style

	// структура класса окна
	wc.cbSize    = sizeof(WNDCLASSEX);
	wc.style    = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc    = WindowProc;    //указатель на функцию обработки сообщений - нужен прототип 
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance    = hInstance;
	wc.hIcon    = LoadIcon(hInstance, L"wildboar");	// 32x32
	//wc.hCursor    = LoadCursor(NULL, IDC_ARROW);
	wc.hCursor    = LoadCursor(hInstance, L"sword");	// нарисован в  мае 2005 - 6 лет назад когда читал Lord_Necron в бумажном виде) 
	wc.hbrBackground= 0;
	wc.lpszMenuName    = 0;
	wc.lpszClassName= L"class1";
	wc.hIconSm    = LoadIcon(hInstance, L"wildboar"); // 16x16

	// Регистрация класса окна
	if (!RegisterClassEx(&wc)) return(0);
	if (fullscreen)                            // Если полноэкранный режим
    {
        dwExStyle=WS_EX_APPWINDOW|WS_CLIPCHILDREN | WS_VISIBLE ;    // Window Extended Style
        dwStyle=WS_POPUP|WS_CLIPCHILDREN | WS_VISIBLE;             // Windows Style
        ShowCursor(FALSE);            // Hide Mouse
		ScreenWidth=width;
		ScreenHeight=height;
    }
    else
    {
        dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE||WS_CLIPCHILDREN | WS_VISIBLE;    // Window Extended Style	// Без иконки  и кнопок свернуть/закрыть
        dwStyle=WS_OVERLAPPEDWINDOW||WS_CLIPCHILDREN | WS_VISIBLE;            // WS_OVERLAPPEDWINDOW в окне делает графическое искажение тк неправильно ставит размеры окна - помню где-то видел выравнивают по Rect
		ScreenWidth=1024;
		ScreenHeight=768;
    }
pos_x=	(width - ScreenWidth + 2)/2 -1;		
pos_y= (height - ScreenHeight + 2)/2 -1;

	
	// Создание окна
	if (!(hwnd = CreateWindowEx(NULL,
		L"class1",             // имя класса
		L"Sex Vodka Beer and TETRIS!", //заглавие окна
		//dwStyle|WS_CLIPCHILDREN| WS_VISIBLE |WS_CLIPSIBLINGS|WS_CHILD   ,
		//WS_POPUP|WS_CLIPCHILDREN | WS_VISIBLE |WS_CLIPSIBLINGS,
		//WS_CLIPCHILDREN | WS_VISIBLE |WS_CLIPSIBLINGS,
		WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
		pos_x,pos_y,    // начальная позиция x,y
		ScreenWidth,	// ширина окна
		ScreenHeight,	// высота окна
		0,              // дескриптор родительского окна
		0,              // дескриптор меню
		hInstance,      // экземпляр этого приложения
		0)))            // дополнительный параметр - creation parms
		return(0);

	ShowWindow(hwnd, SW_SHOWDEFAULT);
	UpdateWindow(hwnd);

	button1 = CreateWindow(L"Button", L"ЗАПУСК",		BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 320,wcslen(L"ЗАПУСК")*25, 35,hwnd,(HMENU)ID_BUTTON1,hInstance,0);	
	button2 = CreateWindow(L"Button", L"ЖИВАЯ ЛЕГЕНДА", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 420,wcslen(L"ЖИВАЯ ЛЕГЕНДА")*25, 35,hwnd,(HMENU)ID_BUTTON2,hInstance,0);	
	button3 = CreateWindow(L"Button", L"Ню, только для взрослых:)",BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 520,wcslen(L"Ню, только для взрослых:)")*25,35,hwnd,(HMENU)ID_BUTTON3,hInstance,0);	
	button4 = CreateWindowEx(0,L"Button", L"ВЫХОД",BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 680, wcslen(L"ВЫХОД")*25, 35,hwnd,(HMENU)ID_BUTTON4,hInstance,0);	

    InitDirect3D(hwnd);
	//DInput = new DirectInput();
	//DInput->InitializeDirectInput(hInstance, hwnd, DISCL_NONEXCLUSIVE|DISCL_FOREGROUND, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
    return true; 
}


//--------------------------------------------------------------------------------------
// OnLostDevice - эта функция обратного вызова вызывается сразу, как Устройство Direct3D
// войдет в состояние потери(потеря устройства) и перед вызовом IDirect3DDevice9::Reset.
// Ресурсы, которые будут восстанавливаться в OnResetDevice callback
// должны освобождаться здесь, что обычно включает все ресурсы D3DPOOL_DEFAULT.
//--------------------------------------------------------------------------------------
void CALLBACK OnLostDevice()
{
    if( pFont )    pFont->OnLostDevice();
    if( pFont_Small ) pFont_Small->OnLostDevice();
	 SAFE_RELEASE( g_pMesh3DText );

}

//-------------------------------------------------
// OnResetDevice - восстановление после перезапуска
//-------------------------------------------------
HRESULT CALLBACK OnResetDevice()
{
    // Восстановление шрифта
    pFont->OnResetDevice();
    pFont_Small->OnResetDevice();
    return S_OK;
}

//--------------
// Вывод графики
//--------------
void Render()
{
	HRESULT hr=0;
    // Тест потери D3D-устройства
    if( FAILED( hr = pDevice->TestCooperativeLevel() ) )
    {
        if( hr == D3DERR_DEVICELOST ) // Устройство потеряно, но перезапуск отложен. Поэтому, визуализация не возможна.
            return; // Выход из цикла, чтобы попробовать снова (примерно через миллисекунду).(подождите за дверью:у нас сейчас секс :-) )
        if( hr == D3DERR_DEVICENOTRESET ) // Устройство потеряно, сброс (перезапуск) возможен  прямо сейчас.
        {
            OnLostDevice();    // подготовить список освобождения всех ресурсов видео-памяти и содержимого задних буферов для перезапуска
            hr = pDevice->Reset(&d3dpp); // Сброс
            if( FAILED(hr) )return; // Выйти, если не получилось
            OnResetDevice(); // Создание ресурсов заново после перезапуска
        }
    return;
    }
	
	Updatedt();



    pDevice ->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );     // очистка экрана
    //pDevice ->Clear( 0, NULL, D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(30,30,50), 1.0f, 0 ); // прикол)

// Начало сцены
  pDevice ->BeginScene();

  	//Updating of camera position and direction
//	GODCamera::RefreshCamera();
 // switch (Game_State)
 // {
	////case intro:
	//case 0:
	//	pFont_Small->DrawText(0,buffer, -1, &rc2, DT_NOCLIP, D3DCOLOR_XRGB(255, 255, 175));
	//	Sleep(5000);
	//	//Game_State=Game_State+1;
	//	

	////case intro2:
	//case 1:
	//	pFont_Small->DrawText(0,L"<ESC>- выход", -1, &rc3, DT_NOCLIP,D3DCOLOR_XRGB(255, 255, 255));
	////case menu
	////case main_process
	////case options
 // }


  // текстурка загораживает и матрицы не настроил
  pFont_Small->DrawText(0,buffer, -1, &rc2, DT_NOCLIP, D3DCOLOR_XRGB(255, 255, 175));
  pFont_Small->DrawText(0,buffer_size, -1, &rc21, DT_NOCLIP, D3DCOLOR_XRGB(135, 255, 145));
  pFont_Small->DrawText(0,buffer_pos_now, -1, &rc22, DT_NOCLIP, D3DCOLOR_XRGB(190, 255, 115));
  //pFont_Small->DrawText(0,buffer_param, -1, &rc3, DT_NOCLIP, D3DCOLOR_XRGB(190, 255, 115));
  //pFont_Small->DrawText(0,buffer_param2, -1, &rc4, DT_NOCLIP, D3DCOLOR_XRGB(190, 255, 115));
  
  
  //	pDevice->SetVertexShader(MY_VERTEX_FORMAT); // мопед от directx8  - потом починить))
	pDevice->SetStreamSource(0, g_pVB, 0,sizeof(SMyVertex));
	pDevice->SetFVF(MY_VERTEX_FORMAT);
	pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

   //// Draw 3D extruded text using a mesh created with D3DXFont
   //     if( g_pMesh3DText != NULL )
   //     {
   //         
   //         ZeroMemory( &mtrl, sizeof( D3DMATERIAL9 ) );
   //         mtrl.Diffuse.r = mtrl.Ambient.r = 0.0f;
   //         mtrl.Diffuse.g = mtrl.Ambient.g = 0.0f;
   //         mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;
   //         mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
   //         pDevice->SetMaterial( &mtrl );
   //         //pDevice->SetTransform( D3DTS_WORLD, &g_matObj2 );
   //         g_pMesh3DText->DrawSubset( 0 );
   //     }

  /*pFont_Small->DrawText(0,L"<ESC>- выход", -1, &rc3, DT_NOCLIP,D3DCOLOR_XRGB(255, 255, 255));
  pFont_Small->DrawText(0,L"<F1> - развернуть", -1, &rc4, DT_NOCLIP, D3DCOLOR_XRGB(115, 115, 255));
  pFont_Small->DrawText(0,L"<F2> - vsync", -1, &rc5, DT_NOCLIP, D3DCOLOR_XRGB(255,15, 115));*/
  // 255,175, 0 - оранжевый
  // матрица мира
	//D3DXMATRIX World;
	//D3DXMatrixIdentity(&World);
	////World._42 = -0.5f; // хитрожопый трюк :)
	//pDevice->SetTransform(D3DTS_WORLD, &World);


	//PlatformMesh->DrawSubset(0); // визуализация модельки поверхности

	//if(DynamicsWorld)
	//{
	//	// расчёт матрицы квадратика на основе физики и визуализация
	//	GetBulletColObjTransform(BoxBody, World);
	//	pDevice->SetTransform(D3DTS_WORLD, &World);
	//	BoxMesh->DrawSubset(0);


	//	// for(int i=0;i<NUM_BALLS; i++) {}
	//	//Get sphere matrix from physics and render it
	//	GetBulletColObjTransform(SphereBody, World);
	//	pDevice->SetTransform(D3DTS_WORLD, &World);
	//	SphereMesh->DrawSubset(0);


	//	//Cylinders created with the D3DXCreateCylinder() object are created sideways,
	//	//so we must offset the rotation by 45 degrees to match the Bullet matrix

	//	//Get cylinder matrix from physics and render it
	//	D3DXMATRIX Offset;
	//	D3DXMatrixIdentity(&Offset);
	//	D3DXMatrixRotationX(&Offset, 1.57f);
	//	GetBulletColObjTransform(CylinderBody, World);
	//	Offset *= World;
	//	pDevice->SetTransform(D3DTS_WORLD, &Offset);
	//	CylinderMesh->DrawSubset(0);

	//	GetBulletColObjTransform(BoxLeftBody, World);
	//	pDevice->SetTransform(D3DTS_WORLD, &World);
	//	BoxLeftMesh->DrawSubset(0);

	//	GetBulletColObjTransform(BoxRightBody, World);
	//	pDevice->SetTransform(D3DTS_WORLD, &World);
	//	BoxRightMesh->DrawSubset(0);
	//}

	//Sleep(1); // гарантирует, что эта функция оттяпает время твоей программы более чем на 1 мс. (==не менее чем на 1 мс. Может 200мс, 300 ... сколько вздумается ...)
//
//if(cube)    DrawObject();
//if(tri)    DrawObject2();

		////банер1
		//// Apply texture image
		//pDevice->SetTexture(0, Texture);
		//pDevice->SetStreamSource(0, lable_1, 0, sizeof(Vertex));
		//pDevice->SetFVF(D3DFVF_D3DVertex);
		//pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);


  
    //// Draw the floor
    //pDevice->SetStreamSource(0, g_pFloorVB, 0, sizeof(s3DVertex));
    //pDevice->SetFVF(FVF3D);
    //pDevice->SetTexture(0, Texture2);
    //D3DXMatrixIdentity(&matWorld);
    //pDevice->SetTransform(D3DTS_WORLD, &matWorld);
    //pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

    //// Draw the billboards
    //pDevice->SetStreamSource(0, g_pBillboardVB, 0, sizeof(s3DVertex));
    //pDevice->SetTexture(0, Texture1);

    //pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
    //D3DXMatrixTranspose(&matWorld, &matView);
    //for(i=0;i<3;i++) {
    //  for(j=0;j<3;j++) {
    //    matWorld._41 = (float)i *  80.0f - 80.0f;
    //    matWorld._42 = 0.0f;
    //    matWorld._43 = (float)j *  80.0f - 80.0f;

    //    pDevice->SetTransform(D3DTS_WORLD, &matWorld);
    //    pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
    //  }
    //}
    //pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

    //// Clear the texture usage
    //pDevice->SetTexture(0, NULL);

		

// Конец сцены
  pDevice ->EndScene();
  pDevice ->Present( NULL, NULL, NULL, NULL ); // визуализировать
}

//void DrawObject()
//{
//    SetWorld();
//    pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE); // формат вершин
//    pDevice->SetStreamSource( 0, pVB, 0, sizeof(MyVertex) );
//    pDevice->SetIndices(pIB);
//    pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVerts, 0, NumTriangles);
//}
//
//void DeleteObject()
//{
//  if(pVB) pVB->Release();
//  if(pIB) pIB->Release();
//  pVB = 0;
//  pIB = 0;
//}
//
//void DrawObject2()
//{
//    pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
//    //pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
//    //pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
//    pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
//    pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA);
//    pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
//        SetWorldZ_RH();
//    pDevice->SetFVF(D3DFVF_MYVERTEX); // формат вершин
//    pDevice->SetStreamSource( 0, pTB, 0, sizeof(MyVertex) );
//    pDevice->SetVertexShader(NULL);
//    pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
//    SetWorldZ_LH();
//    pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,3,2);
//    pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,DWORD(FALSE));
//    pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
//}
//
//void DeleteObject2()
//{
//  if(pTB) pTB->Release();
//  pTB = 0;
//}

//--------
// Очистка 
//--------
void CleanAll()
{
	/*{
	for(int i=DynamicsWorld->getNumCollisionObjects()-1; i>=0; i--)
	{
		btCollisionObject* obj = DynamicsWorld->getCollisionObjectArray()[i];
		btRigidBody* body = btRigidBody::upcast(obj);
		if(body && body->getMotionState() )
		{
			delete body->getMotionState();
		}
		DynamicsWorld->removeCollisionObject(obj);
		delete obj;
	}

	delete GroundShape;
	delete BoxShape;
	delete SphereShape;
	delete CylinderShape;
	delete BoxLeftShape;
	delete BoxRightShape;

	delete DynamicsWorld;
	delete Solver;
	delete Broadphase;
	delete Dispatcher;
	delete CollisionConfiguration;
	}

	PlatformMesh->Release();
	BoxMesh->Release();
	SphereMesh->Release();
	CylinderMesh->Release();
	BoxLeftMesh->Release();
	BoxRightMesh->Release();*/

	ReleaseMutex(Mutex);
	CloseHandle(Mutex);

	//DeleteObject();
	//DeleteObject2();
	//SAFE_RELEASE(Texture1);
	//SAFE_RELEASE(Texture2);
	//SAFE_RELEASE(g_pFloorVB);
	//SAFE_RELEASE(g_pBillboardVB);
	SAFE_RELEASE (g_pTexture);
	SAFE_RELEASE (g_pVB);
	SAFE_RELEASE( g_pMesh3DText );
	SAFE_RELEASE(pFont);
	SAFE_RELEASE(pFont_Small);
	SAFE_RELEASE(pDevice);
	SAFE_RELEASE(pD3D);
	if(fullscreen)
    {
        ChangeDisplaySettings(NULL,0);
        ShowCursor(TRUE);
    }
	
	if (hwnd && !DestroyWindow(hwnd))    // Разрушить Окно
    {
        MessageBox(NULL,L"Не удалось освободить hwnd", L"Ошибка Освобождения Ресурсов",MB_OK | MB_ICONINFORMATION);
        hwnd=0;
    }
    DestroyIcon(wc.hIcon);
    DestroyIcon(wc.hIconSm);
    UnregisterClass(L"class1", wc.hInstance); // Разрегистровать класс
}

//-------------------
// Обработчик событий
//-------------------
LRESULT CALLBACK WindowProc(HWND hwnd,  // Дескриптор окна
                UINT msg,				// Идентификатор сообщения
                WPARAM wParam,			// информация о сообщении
                LPARAM lParam)			// информация о сообщении
{    
    switch(msg)
    {
		// from converting MS-DOS game to windows 95:
	 //  case WM_ACTIVATEAPP:
	 //  {
	 //       // This message is sent when the application is either entering the foreground or leaving it.
		//	foreground = wParam;
		//	InvalidateRect (hwnd, NULL, TRUE);
		//}break;
		//
		//case WM_PAINT:
		//{
		//	if (foreground) 
		//	{
		//		setRepaintAll();
		//	}
		//	else
		//	{
		//		// Paint "Game Paused" in the middle of the screen
		//		PAINTSTRUCT ps;
		//		RECT rect;
		//		HDC hdc = BeginPaint (hwnd, &ps) ;
		//		GetClientRect (hwnd, &rect);
		//		DrawText (hdc, L"Game Paused", -1, &rect,
		//		DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		//		EndPaint (hwnd, &ps);
		//		return 0;
		//	}
		//}



	//}

/*	case WM_CREATE:
		button1 = CreateWindow(L"Button", L"ЗАПУСК",		BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 320,wcslen(L"ЗАПУСК")*25, 35,hwnd,(HMENU)ID_BUTTON1,hInstance,0);	
		button2 = CreateWindow(L"Button", L"ЖИВАЯ ЛЕГЕНДА", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 420,wcslen(L"ЖИВАЯ ЛЕГЕНДА")*25, 35,hwnd,(HMENU)ID_BUTTON2,hInstance,0);	
		button3 = CreateWindow(L"Button", L"Ню, только для взрослых:)",BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 520,wcslen(L"Ню, только для взрослых:)")*25,35,hwnd,(HMENU)ID_BUTTON3,hInstance,0);	
		button4 = CreateWindowEx(0,L"Button", L"ВЫХОД",BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,10, 680, wcslen(L"ВЫХОД")*25, 35,hwnd,(HMENU)ID_BUTTON4,hInstance,0);	
		*/	

	case WM_SIZE:
		{
			// extract size info
			int width_size  = LOWORD(lParam);
			int height_size = HIWORD(lParam);
			// draw the size of the window
			swprintf(buffer_size,L"WM_SIZE   Текущий Размер (%d,%d)", width_size, height_size);
			//swprintf(buffer, L"%ix%i %4.2f", ScreenWidth,ScreenHeight,FPS);
		}
	case WM_MOVE:
		{
			int xpos_now = LOWORD(lParam);
			int ypos_now = HIWORD(lParam);
			swprintf(buffer_pos_now,L"WM_MOVE  Текущая Пзиция (%d,%d)", xpos_now, ypos_now);
			//swprintf(buffer_pos, L"текущая позиция %i %i",pos_x,pos_y);
		}
	case WM_COMMAND: // winAPI кнопки
		{
			//// print out the wparam an lparam
			//swprintf(buffer_param, L"LOWORD(wparam) = %d, HIWORD(wparam) = %d                    ",    LOWORD(wParam), HIWORD(wParam));
			//swprintf(buffer_param2, L"LOWORD(lparam) = 0X%X, HIWORD(lparam) = 0X%X                     ", LOWORD(lParam), HIWORD(lParam));
		 
		 switch(wParam) //the ID is is wParam
            {
				case ID_BUTTON1:
					{
						BASS_SetVolume(0.001f); 
						D3DXCreateTextureFromFile(pDevice, (L"Art/wildboar2.jpg"), &g_pTexture);
							pDevice->SetTexture(0, g_pTexture);
						
						break;
					}
					
				case ID_BUTTON2:
					{
						
							BASS_ChannelStop(mus_start);
							BASS_SetVolume(1.0f); 
							mus_start=BASS_StreamCreateFile(FALSE, "Art/Компьютерные игры - как это делается.ogg",0,0,0);
							D3DXCreateTextureFromFile(pDevice, (L"Art/Алексей Пажитнов © Game.exe.png"), &g_pTexture);
							pDevice->SetTexture(0, g_pTexture);
							BASS_ChannelStop(mus_start);
								
						break;
					}
				
				case ID_BUTTON3:
					{
						BASS_ChannelStop(mus_start);
						// infected.wav из старых KAV потерялось((

						int i=rand()%5;
						if(i>=3)
							{
								BASS_SetVolume(0.1f); 
								mus_start=BASS_StreamCreateFile(FALSE, "Art/1.ogg",0,0,0);
								D3DXCreateTextureFromFile(pDevice, (L"Art/z_5d16718a.jpg"), &g_pTexture);
								pDevice->SetTexture(0, g_pTexture);
							}
						else
							{
								BASS_SetVolume(0.01f); 
								mus_start=BASS_StreamCreateFile(FALSE, "Art/2.ogg",0,0,0);
								D3DXCreateTextureFromFile(pDevice, (L"Art/test.jpg"), &g_pTexture);
								pDevice->SetTexture(0, g_pTexture);
							}
						BASS_ChannelStop(mus_start);
						BASS_SetVolume(0.05f); 
						 break;
					}
				
				case ID_BUTTON4:
					{
						running=false;
						break;
					}
            }

		} break;


     //case WM_KEYDOWN:	
        //{
			/*
			if(wParam == VK_UP)
			{
				if(!CylinderBody->isActive())
					CylinderBody->activate();
				if(!SphereBody->isActive())
					SphereBody->activate();

				CylinderBody->applyForce(btVector3(0.0f, 500.0f, 0.0f), btVector3(0.0f, 0.0f, 0.0f));
				SphereBody->applyForce(btVector3(0.0f, 500.0f, 0.0f), btVector3(0.0f, 0.0f, 0.0f));
			}
			if(wParam == VK_DOWN)
			{
				if(!BoxBody->isActive())
					BoxBody->activate();
				BoxBody->applyForce(btVector3(0.0f, 0.0f, -5000.0f), btVector3(0.0f,0.0f,0.0f));
			}
			if(wParam == VK_LEFT)
			{
				if(!BoxLeftBody->isActive())
					BoxLeftBody->activate();
				BoxLeftBody->applyForce(btVector3(0.0f, 0.0f, 1000.0f), btVector3(0.0f,0.0f,0.0f));
			}
			if(wParam == VK_RIGHT)
			{
				if(!BoxRightBody->isActive())
					BoxRightBody->activate();
				BoxRightBody->applyForce(btVector3(0.0f, 0.0f, 1000.0f), btVector3(0.0f,0.0f,0.0f));
			}
			*/
   //         if(wParam==VK_ESCAPE)
			//{ 
			//	running=false;
			//	/*
			//		PostQuitMessage(0); // отправляет WM_QUIT 
			//		break; // или return(0) - без кого-то из них тут тоже иногда не реагирует на кнопочку эскейп)
			//	*/
			//}
   //         if (wParam==VK_F1)            // если нажата клавиша F1
   //         {
   //             CleanAll();            // Destroy All
   //             fullscreen=!fullscreen;        // переключить Полноэкранный/Оконный Режим
   //             // Заново создать окно
   //             if (!MakeSuperWindow(fullscreen))
   //             {
   //                 MessageBox(NULL,L"Не могу переключить режим экрана",L"Ошибка переключения экрана",MB_OK | MB_ICONINFORMATION);
   //                 return 0;                        // Если не удалось создать Окно, то выйти
   //             }
   //         }
   //         if(wParam==VK_F2)            // если нажата клавиша F2
   //         {
   //             CleanAll();            // Destroy All
   //             VsyncSwitcher=!VsyncSwitcher;    // переключить VsyncSwitcher
   //             // Заново создать окно
   //             if(!MakeSuperWindow(fullscreen))
   //             {
   //                 MessageBox(NULL,L"Не могу переключить режим экрана",L"Ошибка переключения экрана",MB_OK | MB_ICONINFORMATION);
   //                 return 0;        // Если не удалось создать Окно, то выйти
   //             }
   //         }		
			//
   //     }break;

        case WM_CLOSE:		// отличается от Дестроя тем что не ломает все сразу
        {
            PostQuitMessage(0);        // выход из программы
            return(0);
        } break;
    }// конец switch
    return DefWindowProc(hwnd, msg, wParam, lParam); // остальные сообщения
} // конец WindowProc

//------------------------------------------------------------------------------------------------------------------------------------------
// wWinMain()
// Note that lpCmdLine uses the LPSTR data type instead of the LPTSTR data type. This means that WinMain cannot be used by Unicode programs.
// Some programming frameworks might provide an alternative entry point that provides a Unicode command line.
// For example,  the Microsoft Visual Studio C++ complier uses the name wWinMain for the Unicode entry point. 
//------------------------------------------------------------------------------------------------------------------------------------------
INT WINAPI wWinMain(HINSTANCE hInstance,		// Handle to the  current instance of the application.
					HINSTANCE hPrevInstance,	// Handle to the previous instance of the application. This parameter is always NULL.
					LPWSTR lpCmdLine,			// Pointer to a null-terminated string specifying the command line for the application, excluding the program name. !(LPWSTR)!
					int nCmdShow)		// Определяет как показывать окно. (SW_HIDE SW_MAXIMIZE SW_MINIMIZE SW_SHOW SW_SHOWNORMAL SW_SHOWDEFAULT...)
{
	MSG    msg;	memset(&msg,0,sizeof(msg));
	
    if(!MakeSuperWindow(fullscreen))
    {
        return 0;        // не удалось создать Окно->выйти
    }
	
	if (!BASS_Init(-1,44100, 0, hwnd,NULL))	 return 1;		//#define BASS_MUSIC_SURROUND		0x800	// surround sound #define BASS_MUSIC_SURROUND2	0x1000	// surround sound (mode 2)  0=stereo
	float original_os_volume=BASS_GetVolume();	// сохраняем уровень громкости по умолчанию, чтобы узверя не злить меняя его настройки
	BASS_SetVolume(0.05f);
	//str_start=BASS_StreamCreateFile(FALSE, "art/X5 - trailer2.ogg",0,0,0);
	//DWORD mus_start=BASS_StreamCreateFile(FALSE, "Art/start.ogg",0,0,0); // HSTREAM 
	//HSTREAM mus_start=BASS_StreamCreateFile(FALSE, "Art/start.ogg",0,0,0);
	mus_start=BASS_StreamCreateFile(FALSE, "Art/start.ogg",0,0,0);
	
	
    while(running)
    {
        //if(PeekMessage(&msg, hwnd, 0, 0, (foreground?PM_NOYIELD:0)|PM_REMOVE))	// PM_NOREMOVE если вдруг понадобится GetMessage в комбинации с PeekMessage
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                //if(GetMessage(&msg,NULL,0,0))       // Applications under Windows 3.1 had to have a standard place to return control back to the OS. In fact, this was done behind the scenes in the nonobvious GetMessage() function, which is, as you would expect, called from the main loop. Actually, in many typical Windows programs, it is the main loop.
													// The While loop is referred to here as the message pump. It causes Windows to check the pending queue of events for events that are applicable to this application. Here's the weird part: this function returns only when there are messages pending; in other words, this is a blocking call. The return state of GetMessage() is not true if message pending but rather true if message is something other than WM_QUIT. So you can see that this function is completely tailored to a traditional Windows application. Clearly, a game would not want to block in the main loop waiting for the rest of the OS.
				TranslateMessage(&msg);		// call looks for certain combinations of events and translates them into Windows commands. For example, if you have a menu bar with, say, f as a hot key, then pressing alt+f should activate the menu and send a menu command message (as opposed to a keyboard message). Generally speaking, you should keep the TranslateMesssage() call in the message pump and avoid any alt+ combinations in your application.
				DispatchMessage(&msg);		// takes the message and calls the WndProc() you registered for your window. Note that this is not the only time WndProc() will be called; occasionally, the OS will call it directly.
				if(msg.message == WM_QUIT) break;// раньше всегда считал, что эта строчка лишняя), но говорят пусть там сообщения побегают плавнее камера и анимация будут.
            }
		else
			if (KEYDOWN(VK_ESCAPE)) SendMessage(hwnd, WM_CLOSE, 0,0);	// чит на выход) - запутался где чей  hwnd и hInstance - ещё повод лепить свой велосипед))
			
		  if (KEYDOWN(VK_F2))
		  {
                CleanAll();            // Destroy All
                VsyncSwitcher=!VsyncSwitcher;    // переключить VsyncSwitcher
                // Заново создать окно
                if(!MakeSuperWindow(fullscreen))
                {
                    MessageBox(NULL,L"Не могу переключить режим экрана",L"Ошибка переключения экрана",MB_OK | MB_ICONINFORMATION);
                    return 0;        // Если не удалось создать Окно, то выйти
                }
          }	
		   if (KEYDOWN(VK_F1))
            {
                CleanAll();            // Destroy All
                fullscreen=!fullscreen;        // переключить Полноэкранный/Оконный Режим
                // Заново создать окно
                if (!MakeSuperWindow(fullscreen))
                {
                    MessageBox(NULL,L"Не могу переключить режим экрана",L"Ошибка переключения экрана",MB_OK | MB_ICONINFORMATION);
                    return 0;                        // Если не удалось создать Окно, то выйти
                }
            }
 

			Render();
			BASS_ChannelPlay(mus_start, false); // - не знаю как выключить зацикливание)
	
	
	
    } // Конец while
// Возвращение в Windows и освобождение ресурсов
    CleanAll();            // Вызов функции CleanAll()
	BASS_ChannelStop(mus_start);
	Sleep(100); // заглушка от щелчков звук на выходе из-за изменений громкости
	BASS_SetVolume(original_os_volume); // возвразаем громкость сколько было до 
	Sleep(100);	// заглушка от щелчков звук на выходе
	BASS_Free();
    return (int)msg.wParam;
}// Конец WinMain
