
#define WIN32_LEAN_AND_MEAN
#define STRICT

#include <windows.h>
#include <windowsx.h>
#include <winuser.h>
#include <winsock2.h>
#include <commctrl.h>
#include <commdlg.h>
#include <mmsystem.h>
#include <commctrl.h>
#include <shlwapi.h>

#include <io.h>
#include <conio.h>
#include <commctrl.h>
#include <shlwapi.h>

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <math.h>

#define _USE_BETTLEJUICE_

#include "beetlejuice.h"
 
extern void go();

HINSTANCE hInstance=NULL;


ATOM				MyRegisterClass( HINSTANCE hInstance );
HWND				InitInstance( HINSTANCE, int );
LRESULT CALLBACK	WndProc( HWND, UINT, WPARAM, LPARAM );

static void Render(HWND hWnd);


struct RenderSettings
{
	char fileName[MAX_PATH];

	FRtInt width,height;
	FRtFloat pixelAspect;

	// anti-aliasing
	FRtBoolean aaEnable;
	FRtBoolean aaShowSmp;
	FRtInt     aaMinRate;
	FRtInt     aaMaxRate;
	FRtFloat   aaThresh;
	FRtFloat   aaFilterSize;

	// buckets
	FRtInt     bucketSize;
	FRtInt     bucketOrder;
	FRtBoolean bucketReverse;

	// messages
	FRtInt showMessages;
	FRtInt verboseLevel;

	// multithreading
	FRtBoolean mtEnable;
	FRtBoolean mtLowPriority;
	FRtBoolean mtUseAllCPUs;
	FRtInt     mtNumThreads;

	// Flags
	FRtBoolean useDefaultLights;
	FRtBoolean useMappings;
	FRtBoolean useShadows;

	// Raytrace
	FRtBoolean useBlurry;
	FRtBoolean useReflection;
	FRtBoolean useRefraction;
	FRtInt     reflectBounces;
	FRtInt     refractBounces;

	// Sky-Light
	FRtBoolean skyEnable;
	FRtFloat   skyMultiplier;
	FRtColor   skyColor;

	// GI Globals
	FRtBoolean giEnable;
	FRtInt     giBounces;
	FRtBoolean giGICaustics;
	FRtBoolean giShadeBG;
	FRtFloat   giSaturation;
	FRtFloat   giContrast;
	FRtFloat   giContrastRange;
	FRtFloat   giMultiplier;
	FRtFloat   giSecMultiplier;

	// fR-Image GI-Engine
	FRtBoolean giUsePrePass;
	FRtInt     giPrePassRatio;
	FRtBoolean giReuse;
	FRtBoolean giLock;
	FRtInt     giNumRays;
	FRtBoolean giUseSecRays;
	FRtInt     giNumSecRays;
	FRtBoolean giAbsRes;
	FRtInt     giMaxDensity;
	FRtFloat   giMinRadius;
	FRtInt     giMinMaxRatio;

	// color mapping
	FRtBoolean useCMap;
	FRtInt     cmapType;
	FRtFloat   cmapDarkMult;
	FRtFloat   cmapBrightMult;
	FRtBoolean cmapAffectBG;

	RenderSettings()
	{
		width  = 640;
		height = 480;
		pixelAspect = 1.0f;

		aaEnable     = true;
		aaMinRate    = -1;
		aaMaxRate    = 2;
		aaThresh     = 0.03f;
		aaFilterSize = 1.5f;
		aaShowSmp    = false;

		bucketSize    = FRI_OP_BUCKETSIZE_32;
		bucketOrder   = FRI_OP_BUCKETORDER_HILBERT;
		bucketReverse = false;

		showMessages = false;
		verboseLevel = 2;

		mtEnable      = true;
		mtLowPriority = false;
		mtUseAllCPUs  = true;
		mtNumThreads  = 2;

		useDefaultLights = true;
		useMappings      = true;
		useShadows       = true;

		useBlurry      = true;
		useReflection  = true;
		useRefraction  = true;
		reflectBounces = 2;
		refractBounces = 4;

		skyEnable     = true; //true;
		skyMultiplier = 1.0f;
		skyColor[0]   = 1.0f;
		skyColor[1]   = 0.97f;
		skyColor[2]   = 0.84f;

		giEnable        = true;
		giBounces       = 5;
		giGICaustics    = false;
		giShadeBG       = false;
		giSaturation    = 1.0f;
		giContrast      = 0.0f;
		giContrastRange = 1.0f;
		giMultiplier    = 1.4f;
		giSecMultiplier = 1.0f;

		// fR-Image GI-Engine
		giUsePrePass   = true;
		giPrePassRatio = 0;
		giReuse        = false;
		giLock         = false;
		giNumRays      = 256; //300
		giUseSecRays   = true;
		giNumSecRays   = 64;
		giAbsRes       = false;
		giMaxDensity   = 200;
		giMinRadius    = 4.0f; //4.0f;
		giMinMaxRatio  = 8;

		// color mapping
		useCMap        = true;
		cmapType       = FRI_CMAP_TYPE_HSVEXP;
		cmapDarkMult   = 3.0f;
		cmapBrightMult = 1.0f;
		cmapAffectBG   = true;
	}
};

static RenderSettings renderSettings;



int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;

	if(fnLoadFinalRender() == FALSE)
	return 0;

	MyRegisterClass(hInstance);

	if((hWnd =InitInstance( hInstance, nCmdShow)) == NULL) 
	{
		return FALSE;
	}

	PostMessage(hWnd, WM_COMMAND, MAKELONG(1,0), 0L);

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

	return msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= (HICON)NULL;
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)NULL;
	wcex.lpszClassName	= "BEETLEJUICE";
	wcex.hIconSm		= NULL;

	return RegisterClassEx(&wcex);
}

HWND InitInstance(HINSTANCE hInst, int nCmdShow)
{
	HWND hWnd;

	hInstance = hInst; 

	hWnd = CreateWindow("BEETLEJUICE", "BeetleJuice demo v1.0", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	if(!hWnd) 
	{
		return NULL;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return hWnd;
}


void Render(HWND hWnd)
{

	FRtFloat fov = 73.74f;
	FRtFloat specular_strength=0.0f;
	FRtBoolean force2side=true;
	FRtColor background_color,ambient_color,globallight_level;
	
	FRtMatrix worldToCam;
	worldToCam[0][0]=0.707107f; worldToCam[0][1]=0.353553f; worldToCam[0][2]=-0.612372f; worldToCam[0][3]=0.000000f;
	worldToCam[1][0]=-0.707107f; worldToCam[1][1]=0.353553f; worldToCam[1][2]=-0.612372f; worldToCam[1][3]=0.000000f;
	worldToCam[2][0]=0.000000f; worldToCam[2][1]=0.866025f; worldToCam[2][2]=0.500000f; worldToCam[2][3]=0.000000f;
	worldToCam[3][0]=0.000000f; worldToCam[3][1]=0.000000f; worldToCam[3][2]=-5.000000f; worldToCam[3][3]=1.000000f;

	FRiBegin(FRI_NULL);
	
		FRiFormat(renderSettings.width,renderSettings.height,renderSettings.pixelAspect);

		FRiDisplay("c:\\beetlejuice.jpg", FRI_FRAMEBUFFER, FRI_RGBA, FRI_NULL);


		FRiOption("",
			FRI_OP_APPHANDLE,        hWnd,
			//FRI_OP_PROGRESSCALLBACK, &progDialog,
			FRI_OP_TEXTURE_DIRECTORY,"textures",
			FRI_NULL);

		FRtInt tmode=FRI_OP_GBUFFER_MODE_HDTEMP;
		FRtInt tblockSize=64;

		//FRiOption(FRI_OP_TBUFFER,
		//	FRI_OP_TBUFFER_MODE,       &tmode,
		//	FRI_OP_TBUFFER_BLOCKWIDTH, &tblockSize,
		//	FRI_NULL);

		// setup environment

		background_color[0] = 0.0f; //0.2f;
		background_color[1] = 0.0f; //0.8f;
		background_color[2] = 0.0f; //8f;

		ambient_color[0] = 0.0f;
		ambient_color[1] = 0.0f;
		ambient_color[2] = 0.0f;
	
		globallight_level[0] = 1.0f;
		globallight_level[1] = 1.0f;
		globallight_level[2] = 1.0f;
		
		FRiOption(FRI_OP_ENVIRONMENT,
			FRI_OP_BACKGROUNDCOLOR,  background_color,
			FRI_OP_AMBIENTCOLOR,     ambient_color,
			FRI_OP_GLOBALLIGHTLEVEL, globallight_level,
			FRI_NULL);

		// anti-aliasing
		FRiOption(FRI_OP_AA,
			FRI_OP_ANTIALIAS,     &renderSettings.aaEnable,
			FRI_AA_ADAPT_MINRATE, &renderSettings.aaMinRate,
			FRI_AA_ADAPT_MAXRATE, &renderSettings.aaMaxRate,
			FRI_AA_ADAPT_THRESH,  &renderSettings.aaThresh,
			FRI_AA_ADAPT_SHOWSMP, &renderSettings.aaShowSmp,
			FRI_NULL);

		// setup the AA-filter
		//FRiPixelFilter(FRiGaussianFilter, renderSettings.aaFilterSize, renderSettings.aaFilterSize);
		//FRiPixelFilter(FRiBoxFilter, renderSettings.aaFilterSize, renderSettings.aaFilterSize);
		//FRiPixelFilter(FRiCatmullRomFixFilter, renderSettings.aaFilterSize, renderSettings.aaFilterSize);
		//FRiPixelFilter(FRiMitchellNetravalliFilter, 4.0f, 4.0f); // fixed size !!
		//FRiPixelFilter(FRiBlackmanFilter, 4.0f, 4.0f);
		// setup the AA-filter
		FRiPixelFilter(FRiGaussianFilter, renderSettings.aaFilterSize, renderSettings.aaFilterSize);

		//FRtFloat gain;
		//FRtFloat gamma;
		//gain = 1.0f;
		//gamma = 1.8f;
		//FRiExposure (gain, gamma);
		FRtBoolean useGamma=false;
		FRtFloat   gamma=1.8f;

		// Display Gamma correction
		FRiOption(FRI_OP_GAMMA,
			FRI_OP_GAMMA_ENABLE,  &useGamma,
			FRI_OP_GAMMA_DISPLAY, &gamma,
			FRI_NULL);

		// buckets
		FRiOption(FRI_OP_BUCKETS,
			FRI_OP_BUCKETSIZE,  &renderSettings.bucketSize,
			FRI_OP_BUCKETORDER, &renderSettings.bucketOrder,
			FRI_OP_BUCKETORDER_REVERSE, &renderSettings.bucketReverse,
			FRI_NULL);

		// messages
		FRiOption("",
			FRI_OP_DISPLAYMESSAGES, &renderSettings.showMessages,
			FRI_OP_VERBOSELEVEL,    &renderSettings.verboseLevel,
			FRI_NULL);

		// multithreading
		FRiOption(FRI_OP_MULTITHREADING,
			FRI_OP_USEMULTITHREADING,  &renderSettings.mtEnable,
			FRI_OP_LOWPRIORITYTHREADS, &renderSettings.mtLowPriority,
			FRI_OP_USEALLPROCESSORS,   &renderSettings.mtUseAllCPUs,
			FRI_OP_CUSTOMNUMTHREADS,   &renderSettings.mtNumThreads,
			FRI_NULL);

		// Accelerator
		FRiOption(FRI_OP_ISECT,
			FRI_OP_ISECT_ENGINE,	FRI_SCENEMSP,
			FRI_NULL);

		// Flags
		FRiOption("",
			FRI_OP_FORCE2SIDE,       &force2side,
			FRI_OP_MAPPING,          &renderSettings.useMappings,
			FRI_OP_USEDEFAULTLIGHTS, &renderSettings.useDefaultLights,
			FRI_OP_SHADOWS,          &renderSettings.useShadows,
			FRI_NULL);

		// Ratyracer
		FRiOption(FRI_OP_RAYTRACE,
			FRI_OP_BLURRYENABLE,   &renderSettings.useBlurry,
			FRI_OP_USEREFRACTION,  &renderSettings.useRefraction,
			FRI_OP_USEREFLECTION,  &renderSettings.useReflection,
			FRI_OP_REFLECTBOUNCES, &renderSettings.reflectBounces,
			FRI_OP_REFRACTBOUNCES, &renderSettings.refractBounces,
			FRI_NULL);
	
		// Color Mapping
		FRiOption(FRI_OP_CMAP,
			FRI_OP_CMAP_ENABLE,     &renderSettings.useCMap,
			FRI_OP_CMAP_TYPE,       &renderSettings.cmapType,
			FRI_OP_CMAP_DARKMULT,   &renderSettings.cmapDarkMult,
			FRI_OP_CMAP_BRIGHTMULT, &renderSettings.cmapBrightMult,
			FRI_OP_CMAP_AFFECTBG,   &renderSettings.cmapAffectBG,
			FRI_NULL);


		// SkyLight
		FRiOption(FRI_OP_SKY,
			FRI_OP_SKY_ENABLE,     &renderSettings.skyEnable,
			FRI_OP_SKY_MULTIPLIER, &renderSettings.skyMultiplier,
			FRI_OP_SKY_COLOR,      &renderSettings.skyColor,
			FRI_NULL);

		FRtFloat thresh=0.01f;

		// GI 
		FRiOption(FRI_OP_GI,
			FRI_OP_GI_ENABLE,        &renderSettings.giEnable,
			FRI_OP_GI_BOUNCES,       &renderSettings.giBounces,
			FRI_OP_GI_SHADESPECULAR, &renderSettings.giGICaustics,
			FRI_OP_GI_SHADEBG,       &renderSettings.giShadeBG,
			FRI_OP_GI_SATURATION,    &renderSettings.giSaturation,
			FRI_OP_GI_CONTRAST,      &renderSettings.giContrast,
			FRI_OP_GI_CONTRASTRANGE, &renderSettings.giContrastRange,
			FRI_OP_GI_MULTIPLIER,    &renderSettings.giMultiplier,
			FRI_OP_GI_SECMULTIPLIER, &renderSettings.giSecMultiplier,


			FRI_OP_GI_ENGINE, "fraqmc",
			"threshold", &thresh,
		FRI_NULL);

		FRiOption(FRI_IMAGE_GI,
			FRI_IMAGE_GI_USEPREPASS,  &renderSettings.giUsePrePass,
			FRI_IMAGE_GI_PREPASS_STEPSIZE, &renderSettings.giPrePassRatio,
			FRI_IMAGE_GI_REUSE,       &renderSettings.giReuse,
			FRI_IMAGE_GI_LOCK,        &renderSettings.giLock,
			FRI_IMAGE_GI_NUMRAYS,     &renderSettings.giNumRays,
			FRI_IMAGE_GI_USESECRAYS,  &renderSettings.giUseSecRays,
			FRI_IMAGE_GI_NUMSECRAYS,  &renderSettings.giNumSecRays,
			FRI_IMAGE_GI_ABSRES, &renderSettings.giAbsRes,
			FRI_IMAGE_GI_MAXDENSITY,  &renderSettings.giMaxDensity,
			FRI_IMAGE_GI_MINRADIUS,   &renderSettings.giMinRadius,
			FRI_IMAGE_GI_MAXMINRATIO, &renderSettings.giMinMaxRatio,
			FRI_IMAGE_GI_LOADGIM,     "C:\\kitchen.gim",
			FRI_IMAGE_GI_SAVEGIM,     "C:\\kitchen.gim",

			FRI_NULL);


                

		FRtBoolean infoEnable=false;

		FRiOption(FRI_OP_INFO,
			FRI_OP_INFO_ENABLE, &infoEnable,
			FRI_OP_INFO_HEADER, "%product version %version",
			FRI_OP_INFO_FOOTER, "render time: %rendertime, num. objects %numnodes, num. faces %numfaces",
			FRI_NULL);

		FRiProjection("perspective", FRI_FOV, &fov, FRI_NULL);	// setup camera

		FRiIdentity();
		FRiTransform(worldToCam);

		FRiWorldBegin();	
		
		go();

		FRiWorldEnd();
			
	FRiEnd();
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int low, hiw;

	switch(message) 
	{
		case WM_COMMAND:
			low    = LOWORD(wParam); 
			hiw = HIWORD(wParam); 
			switch( low ) 
			{
				case 1:
				   Render (hWnd);
				   break;
				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;

		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}


