// rtray.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

#include <windows.h>
#include <math.h>

#include "rt.h"




//  scene definition







//---- blit

void blit(HDC dc, int *buf, int w, int h)
{
  BITMAPINFO bmi;

  bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  bmi.bmiHeader.biWidth = w;
  bmi.bmiHeader.biHeight = -h;
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biBitCount = 32;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biSizeImage = 0;
  bmi.bmiHeader.biXPelsPerMeter = 1000;
  bmi.bmiHeader.biYPelsPerMeter = 1000;
  bmi.bmiHeader.biClrUsed = 0;
  bmi.bmiHeader.biClrImportant = 0;

  StretchDIBits(
    dc,
    0, 0, w, h,
    0, 0, w, h,
    (LPVOID)buf,
    (LPBITMAPINFO)&bmi,
    DIB_RGB_COLORS, SRCCOPY
  );

}



//---- DATA

HINSTANCE hMainInstance;

int mouse_x = 0, mouse_y = 0;
int mouse_xstart = 0, mouse_ystart = 0;

bool mouse_drag = false;

float rx=0, ry=0, rrx=0, rry=0;

int width=480, height=360;
//int width=160, height=120;

char szAppName[128] = "Realtime Raytrace";

HWND hMainWindow;



RT_SCENE *scene;
RT_VIEW *view;


void startup()
{
  view = rt_view_create( width, height );
  scene = rt_scene_create();

  int i;

  int count = 32;

  for( i=0; i<=count; i++)
  {
    float a = i * 4 * 3.141f / count;
    float d = cosf( a - 3.141f*0.5f );
    float x = sinf( a*3.32f ) * 3.0f;
    float y = sinf( 1.23f - a*1.91f ) * 3.0f;
    float z = cosf( a*2.12f ) * 3.0f;
    float r = 1+0.5f*d;
    rt_scene_sphere( scene, x, y, z, r, 0x873261 + i*0x76A72F );
  }
}

void shutdown()
{
  rt_scene_destroy( scene );
  rt_view_destroy( view );
}

void redraw( HDC dc )
{
  rt_scene_setRotation( scene, rx, ry );
//  rt_render_area( scene, view->w/2-3, view->h/2-3, view->w/2+3, view->h/2+3, view );
//  rt_render_area( scene, 0, 0, width, height, view );
  rt_render( scene, view );
//  rt_drawHUD( scene, view );

  rt_drawFrameRate( view );
  blit( dc, (int*)view->buf, view->w, view->h );
}



//---- WinProc ---------------------------------------------------------------//

LRESULT CALLBACK WinProc(HWND hwnd, UINT uiMsg, UINT wParam, LONG lParam)
{
  HDC dc;
  PAINTSTRUCT ps;

  switch(uiMsg) {

  case WM_CREATE:
    startup();
    SetTimer(hwnd, 1, 10, NULL);
    break;

  case WM_TIMER:
    dc = GetDC(hwnd);
    redraw(dc);
    ReleaseDC(hwnd, dc);
    return 0L;

  case WM_PAINT:
    dc = BeginPaint(hwnd, &ps);
    redraw(dc);
    EndPaint(hwnd, &ps);
    return 0L;

  case WM_LBUTTONDOWN:
    mouse_xstart = HIWORD(lParam);
    mouse_ystart = LOWORD(lParam);
    mouse_drag = true;
    SetCapture(hwnd);
    return 0L;

  case WM_MOUSEMOVE:
    mouse_x = HIWORD(lParam);
    mouse_y = LOWORD(lParam);

    if(mouse_drag)
    {
      ry -= (mouse_y-mouse_ystart) * 0.0004f;
      rx += (mouse_x-mouse_xstart) * 0.0004f;
      mouse_xstart = mouse_x;
      mouse_ystart = mouse_y;
    }
    return 0L;

  case WM_LBUTTONUP:
    mouse_drag = false;
    ReleaseCapture();
    return 0L;

/*
  case WM_NCHITTEST:
    return HTCAPTION;
*/

  case WM_DESTROY:
	  shutdown();
    KillTimer(hwnd, 1);
    PostQuitMessage(0);
    return 0L;
  }

  return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}



//---- WinMain ---------------------------------------------------------------//

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  WNDCLASS wndclass;
  MSG msg;
  RECT rc;

  hMainInstance = hInstance;

  if(hPrevInstance) return 1;

  //- Create window class

  wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  wndclass.lpfnWndProc   = WinProc;
  wndclass.cbClsExtra    = 0;
  wndclass.cbWndExtra    = 0;
  wndclass.hInstance     = hInstance;
  wndclass.hIcon         = NULL;
  wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
  wndclass.lpszMenuName  = NULL;
  wndclass.lpszClassName = szAppName;

  if(!RegisterClass(&wndclass)) return 1;

  //- Create main window

  GetWindowRect(GetDesktopWindow(), &rc);

  hMainWindow = CreateWindowEx(
    0,
    szAppName,
    szAppName,
    WS_OVERLAPPEDWINDOW,
    (rc.right-width)/2,
    (rc.bottom-height)/2,
    width,
    height,
    NULL,
    NULL,
    hInstance,
    NULL
  );

  if(!hMainWindow) return 1;

  ShowWindow(hMainWindow, SW_SHOW);

  //- Message loop

  while(TRUE) {
    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
      if (msg.message == WM_QUIT) return TRUE;
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    HDC dc = GetDC(hMainWindow);
    redraw(dc);
    ReleaseDC(hMainWindow, dc);
  }

  return 0;
}



//---- END OF FILE -----------------------------------------------------------//
