/*======================================================================================*/
/* Render the scene using the Persistence Of Vision ray-tracer				*/
/*											*/
/* AUTHOR:	Gabor Nagy								*/
/* DATE:	1996-Sep-23 12:41:38							*/
/*											*/
/* This example file is freely modifiable and can be used for any purpose.		*/
/*											*/
/* EQUINOX-3D, 3DPanel and 3DLib Copyright (C) 1995 By Gabor Nagy. All rights reserved.	*/
/*======================================================================================*/

// x-povray +Linclude +Iscenes/lights/spotlite.pov +V +W640 +H480 +Oa.tif
// x-povray +Linclude +Iscenes/lights/spotlite.pov +D +W640 +H480
// /usr1/povray-3.5/povray +L/usr1/povray-3.5/include +Iscenes/lights/spotlite.pov +D +W640 +H480 tmp.pov

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include <EPrefs.h>

#include <EGUI/PushButton.h>
#include <EGUI/Dialog.h>

#include <E3D/3DWindow.h>


static char		E3d_POVDir[MAXPATHLEN+1];

static EResource	E3d_POVSettings[]=
{
 { "POVDir",		EResSTRING, 	E3d_POVDir, NULL },
 { "",			EResSEMMI,	NULL, NULL }
};


static EguiItem		E3d_MenuButton=NULL;


/*==============================================================*/
/* Output scene in POV format and call x-povray			*/
/*==============================================================*/
static void E3dp_Render(EguiItem LW, EPointer LClientData, EPointer LCallData)
{
 E3dScene*		LScene=E3d_Scene;
 E3dRenderInfo*		LRenderInfo=&(LScene->RenderInfo);
 E3dCamera*		LCamera;
 E3dLight*		LLight;
 E3dPolyGroup**		LPolyGroups;
 E3dPolyGroup*		LPolyGroup;
 E3dRTriangle*		LRTriangle;
 E3dMaterial*		LMaterial;
 char			LCommand[MAXPATHLEN+1];
 unsigned long		LC, LTN, LTCnt,
			LNumOfPolyGroups;
 float			LFA, LFS, LLumaDiffuse;
 FILE*			LOutFile;


 EGUI_Sync(E3dp_EventLoopFunction);
 EGUI_Sync(E3dp_EventLoopFunction);

 if((LOutFile=fopen("tmp.pov", "w"))!=NULL)
 {
  fprintf(LOutFile, "// POV file output by EQUINOX\n//\n");


  fprintf(LOutFile, "#include \"colors.inc\"\n");
  fprintf(LOutFile, "#include \"shapes.inc\"\n");
  fprintf(LOutFile, "#include \"glass.inc\"\n");

  if(E3dp_Main3DWindow)
  {
   LCamera=&(E3dp_Main3DWindow->PerspectiveCamera);

   fprintf(LOutFile, "\ncamera {\n");
   fprintf(LOutFile, " location <%f, %f, %f>\n", -LCamera->Position.X, LCamera->Position.Y, LCamera->Position.Z);
   fprintf(LOutFile, " look_at <%f, %f, %f>\n", -LCamera->InterestPoint.X, LCamera->InterestPoint.Y, LCamera->InterestPoint.Z);
//   fprintf(LOutFile, " up <%f, %f, %f>\n", -LCamera->UpVector.X, LCamera->UpVector.Y, LCamera->UpVector.Z);
   fprintf(LOutFile, " angle %f\n", LCamera->FieldOfView*1.25);
   fprintf(LOutFile, "}\n");

   for(LC=0; LC<LScene->NumOfLights; LC++)
   {
    LLight = LScene->Lights[LC];
    fprintf(LOutFile, "\nlight_source { <%f,%f,%f> color <%f,%f,%f> }\n", -LLight->Position.X, LLight->Position.Y, LLight->Position.Z, LLight->Color.R, LLight->Color.G, LLight->Color.B);
   }

//   fprintf(LOutFile, "\nbackground { color SkyBlue }\n");


   if((LNumOfPolyGroups=E3d_SceneGetRenderTriangles(LScene, &(LScene->RenderInfo), NULL))>0)
   {
    LPolyGroups=LScene->RenderPolyGroups;
    for(LC=0; LC < LNumOfPolyGroups; LC++)
    {
     LPolyGroup=LPolyGroups[LC];

     if((LTN=LPolyGroup->NumOfTriangles)>0)
     {
      LRTriangle=LPolyGroup->Triangles;

      fprintf(LOutFile, "\nunion\n{\n");

      if(LPolyGroup->Flags&E3dUSE_VERTEX_NORMALS)
      {
       for(LTCnt=0;LTCnt<LTN; LTCnt++, LRTriangle++)
       {
	fprintf(LOutFile, "smooth_triangle { <%f,%f,%f>, <%f,%f,%f>, ", -LRTriangle->V0[E3dX], LRTriangle->V0[E3dY], LRTriangle->V0[E3dZ], -LRTriangle->Normal0.X, LRTriangle->Normal0.Y, LRTriangle->Normal0.Z);

	fprintf(LOutFile, "<%f,%f,%f>, <%f,%f,%f>, ", -LRTriangle->V1[E3dX], LRTriangle->V1[E3dY], LRTriangle->V1[E3dZ], -LRTriangle->Normal1.X, LRTriangle->Normal1.Y, LRTriangle->Normal1.Z);

	fprintf(LOutFile, "<%f,%f,%f>, <%f,%f,%f> }\n", -LRTriangle->V2[E3dX], LRTriangle->V2[E3dY], LRTriangle->V2[E3dZ], -LRTriangle->Normal2.X, LRTriangle->Normal2.Y, LRTriangle->Normal2.Z);
       }
      }
      else
      {
       for(LTCnt=0;LTCnt<LTN; LTCnt++, LRTriangle++)
       {
	fprintf(LOutFile, "triangle { <%f,%f,%f>, ", -LRTriangle->V0[E3dX], LRTriangle->V0[E3dY], LRTriangle->V0[E3dZ]);

	fprintf(LOutFile, "<%f,%f,%f>, ", -LRTriangle->V1[E3dX], LRTriangle->V1[E3dY], LRTriangle->V1[E3dZ]);

	fprintf(LOutFile, "<%f,%f,%f> }\n", -LRTriangle->V2[E3dX], LRTriangle->V2[E3dY], LRTriangle->V2[E3dZ]);
       }
      }

      LMaterial=LPolyGroup->DrawingMaterial;
      fprintf(LOutFile, "\npigment { color <%f %f %f> }\n", LMaterial->Diffuse.R*1.6, LMaterial->Diffuse.G*1.6, LMaterial->Diffuse.B*1.6);
      switch(LMaterial->Type)
      {
       case E3dMAT_LAMBERT:
//       fprintf(LOutFile, "\nfinish { ambient %f }\n", LMaterial->Ambient.G/(LMaterial->Diffuse.G+0.0001)*0.2 );
       break;

       case E3dMAT_PHONG:
       case E3dMAT_BLINN:
        LLumaDiffuse=EcM_Luma(LMaterial->Diffuse.R, LMaterial->Diffuse.G, LMaterial->Diffuse.B);

	if(LLumaDiffuse>0.001)
        {
         LFA=EcM_Luma(LMaterial->Ambient.R, LMaterial->Ambient.G, LMaterial->Ambient.B)/LLumaDiffuse*0.15;
         LFS=EcM_Luma(LMaterial->Specular.R, LMaterial->Specular.G, LMaterial->Specular.B)/LLumaDiffuse*0.36;
        }
	else { LFA=0.0;LFS=0.0; }

	if(LMaterial->Reflectivity==0.0) fprintf(LOutFile, "\nfinish { ambient %f specular %f }\n", LFA, LFS );
	else fprintf(LOutFile, "\nfinish { ambient %f specular %f reflection %f }\n", LFA, LFS, LMaterial->Reflectivity);

        if(LMaterial->Transparency>0.0)
        {
         fprintf(LOutFile, "\ninterior{I_Glass caustics 1}\n");
        }
       break;
      }

 /*
 finish  {
     ambient 0.1
     diffuse 0.1
     reflection 0.1
     specular 0.8
     roughness 0.003
     phong 1
     phong_size 400
 }

	 interior{I_Glass
	     caustics 1
//             fade_distance 30
//             fade_power 1
	 }
 */



      fprintf(LOutFile, "\n}\n");	// Close union
     }
    }

    E3d_SceneFreeRenderTriangles(E3d_Scene);
   }

/*
   fprintf(LOutFile, "\nplane { y, -3\n");
   fprintf(LOutFile, " pigment { color Blue }\n");
   fprintf(LOutFile, "}\n");
*/

//   printf("Total # of polygons: %d\n", LTotalPolyNum);fflush(stdout);
  }

  fclose(LOutFile);

// Invoke POV
//

  if(LRenderInfo->StartPixelSize>1)
  {
   if(LRenderInfo->AntiAliasing) sprintf(LCommand, "%s/povray +L%s/include tmp.pov +D +W%d +H%d +SP%d +EP1 +P +A +FN +Oa.png&", E3d_POVDir, E3d_POVDir, E3d_Scene->RenderInfo.WindowXSize, E3d_Scene->RenderInfo.WindowYSize, LRenderInfo->StartPixelSize);
   else sprintf(LCommand, "%s/povray +L%s/include tmp.pov +D +W%d +H%d +SP%d +EP1 +P +FN +Oa.png&", E3d_POVDir, E3d_POVDir, E3d_Scene->RenderInfo.WindowXSize, E3d_Scene->RenderInfo.WindowYSize, LRenderInfo->StartPixelSize);
  }
  else
  {
   if(LRenderInfo->AntiAliasing) sprintf(LCommand, "%s/povray +L%s/include tmp.pov +D +W%d +H%d +EP1 +P +A +FN +Oa.png&", E3d_POVDir, E3d_POVDir, E3d_Scene->RenderInfo.WindowXSize, E3d_Scene->RenderInfo.WindowYSize);
   else sprintf(LCommand, "%s/povray +L%s/include tmp.pov +D +W%d +H%d +EP1 +P +FN +Oa.png&", E3d_POVDir, E3d_POVDir, E3d_Scene->RenderInfo.WindowXSize, E3d_Scene->RenderInfo.WindowYSize);
  }

/*
  if(LRenderInfo->AntiAliasing) sprintf(LCommand, "%s/povray +L%s/include +I tmp.pov +D +W%d +H%d +SP64 +EP1 +P +A +FN +Oa.png&", E3d_POVDir, E3d_POVDir, E3d_Scene->RenderInfo.WindowXSize, E3d_Scene->RenderInfo.WindowYSize);
  else sprintf(LCommand, "%s/povray +L%s/include +I tmp.pov +D +W%d +H%d +SP64 +EP1 +P +FN +Oa.png&", E3d_POVDir, E3d_POVDir, E3d_Scene->RenderInfo.WindowXSize, E3d_Scene->RenderInfo.WindowYSize);
*/


  system(LCommand);
 }
}


/*======================================*/
/* Entry point of the plugin		*/
/*======================================*/
int Plugin_Init()
{
 E3d_POVDir[0]='\0';
 E3dp_ReadSettings(".povrender", E3d_POVSettings);
 E3d_MenuButton=EGUI_AddPushButton("Menu->Render", "Use POV", '\0', NULL, NULL, FALSE, NULL, E3dp_Render, (EPointer)0);

 return(0);
}


/*======================================*/
/* Exit method of the plugin		*/
/*======================================*/
int Plugin_Exit()
{
 if(E3d_MenuButton) EGUI_DestroyItem(E3d_MenuButton);

 return(0);
}
