/*======================================================================*/
/* Drawing macros etc.							*/
/*									*/
/* AUTHOR:	Gabor Nagy						*/
/* DATE:	1996-Jan-09 23:21:35					*/
/*									*/
/* 3DPanel(TM) Copyright (C) 1995 by Gabor Nagy. All rights reserved.	*/
/*======================================================================*/
#ifndef _E3DDrawing_h
#define _E3DDrawing_h


#ifndef _E3DPanel_h
#include <E3D/Panel.h>
#endif


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif


//================================================
// Set up a 2DTexture for drawing with OpenGL
//================================================
#define E3dGLM_Setup2DTexture(m2DTexture)\
{\
 if(m2DTexture->GLAlphaFunction==GL_ALWAYS) glDisable(GL_ALPHA_TEST);\
 else { glEnable(GL_ALPHA_TEST);glAlphaFunc(m2DTexture->GLAlphaFunction, m2DTexture->GLAlphaReference); }\
\
 glBindTexture(GL_TEXTURE_2D, m2DTexture->GLIndex);\
\
 if(m2DTexture->SCount>1) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);\
 else glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);\
\
 if(m2DTexture->TCount>1) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);\
 else glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);\
\
/* Apparently glBindTexture won't set these..*/\
 switch(m2DTexture->MappingMethod)\
 {\
  case E3dTXT_ENVIRONMENT_MAP:\
   glEnable(GL_TEXTURE_GEN_S);\
   glEnable(GL_TEXTURE_GEN_T);\
  break;\
\
  default:\
   glDisable(GL_TEXTURE_GEN_S);\
   glDisable(GL_TEXTURE_GEN_T);\
  break;\
 }\
}




//------------------------------------------------
// Draw Polygon
//------------------------------------------------
#define E3dM_DrawPolygon()\
 if((mITriangle=mPolygon->ITriangles)==NULL)\
 {\
  mVertexNode=mPolygon->VertexNodes;\
  mVN=mPolygon->NumOfExteriorVertices;\
  glBegin(GL_POLYGON);\
   for(mVC=0;mVC<mVN;mVC++, mVertexNode++) MglVertex3v(mVertexNode->GLVertex);\
  glEnd();\
 }\
 else\
 {\
  mPC1=mPolygon->NumOfTriangles;\
  glBegin(GL_TRIANGLES);\
  do\
  {\
   mVertexNodeP=mITriangle->VertexNodes;\
   MglVertex3v((mVertexNodeP[0])->GLVertex);\
   MglVertex3v((mVertexNodeP[1])->GLVertex);\
   MglVertex3v((mVertexNodeP[2])->GLVertex);\
   mITriangle++;\
  } while(--mPC1);\
  glEnd();\
 }


//------------------------------------------------
// Draw Polygon with Vertex normals
//------------------------------------------------
#define E3dM_DrawPolygonVertexNormal()\
 if((mITriangle=mPolygon->ITriangles)==NULL)\
 {\
  mVN=mPolygon->NumOfExteriorVertices;\
  mVertexNode=mPolygon->VertexNodes;\
  glBegin(GL_POLYGON);\
   for(mVC=0;mVC<mVN;mVC++, mVertexNode++) { MglNormal3v(mVertexNode->GLNormal);MglVertex3v(mVertexNode->GLVertex); }\
  glEnd();\
 }\
 else\
 {\
  mPC1=mPolygon->NumOfTriangles;\
  glBegin(GL_TRIANGLES);\
  do\
  {\
   mVertexNodeP=mITriangle->VertexNodes;\
   mVertexNode=mVertexNodeP[0];MglNormal3v(mVertexNode->GLNormal);MglVertex3v(mVertexNode->GLVertex);\
   mVertexNode=mVertexNodeP[1];MglNormal3v(mVertexNode->GLNormal);MglVertex3v(mVertexNode->GLVertex);\
   mVertexNode=mVertexNodeP[2];MglNormal3v(mVertexNode->GLNormal);MglVertex3v(mVertexNode->GLVertex);\
   mITriangle++;\
  } while(--mPC1);\
  glEnd();\
 }


#define E3dpM_DrawPolygonContours()\
 mVertexNode=mPolygon->VertexNodes;\
 mVN=mPolygon->NumOfExteriorVertices;\
 glBegin(GL_LINE_LOOP);\
  for(mVC=0;mVC<mVN;mVC++,mVertexNode++) MglVertex3v(mVertexNode->GLVertex);\
 glEnd();\
 if(mPolygon->NumOfVertexNodes>mVN)\
 {\
  mVN=mPolygon->NumOfVertexNodes;\
  glBegin(GL_LINE_LOOP);\
   mVC++;mVertexNode++;\
   for(;mVC<mVN;mVC++,mVertexNode++)\
   {\
    if(mVertexNode->VertexID!=-1) MglVertex3v(mVertexNode->GLVertex);\
    else glEnd();\
   }\
  glEnd();\
 }



//------------------------------------------------
// Draw TriangleStrip with constant color
//------------------------------------------------
#define E3dM_DrawTriangleStripConst()\
 mVN=mTriangleStrip->NumOfVertices;\
 mVertexNode=mTriangleStrip->VertexNodes;\
 glBegin(GL_TRIANGLE_STRIP);\
  for(mVC=0;mVC<mVN;mVC++, mVertexNode++) { MglVertex3v(mVertexNode->GLVertex); }\
 glEnd();


//------------------------------------------------
// Draw Shaded TriangleStrip
//------------------------------------------------
#define E3dM_DrawTriangleStripVertexNormal()\
 mVN=mTriangleStrip->NumOfVertices;\
 mVertexNode=mTriangleStrip->VertexNodes;\
 glBegin(GL_TRIANGLE_STRIP);\
  for(mVC=0;mVC<mVN;mVC++, mVertexNode++) { MglNormal3v(mVertexNode->GLNormal);MglVertex3v(mVertexNode->GLVertex); }\
 glEnd();






//------------------------------------------------
// Draw PolyGroup with constant color
//------------------------------------------------
#define E3dM_DrawPolyGroupConstSolid()\
{\
 E3dPolygon*		mPolygon;\
 E3dITriangle*		mITriangle;\
 E3dTriangleStrip*	mTriangleStrip;\
 E3dVertexNode*		mVertexNode;\
 E3dVertexNode**	mVertexNodeP;\
 unsigned int		mPolyCnt, mPC1,\
			mVC, mVN;\
\
\
 if((mPolyCnt=LPolyGroup->NumOfTriangleStrips)>0)\
 {\
  glDisable(GL_CULL_FACE);\
  mTriangleStrip=LPolyGroup->TriangleStrips;\
  do\
  {\
   E3dM_DrawTriangleStripConst();\
   mTriangleStrip++;\
  } while(--mPolyCnt);\
  glEnable(GL_CULL_FACE);\
 }\
 else\
 {\
  if(LPolyGroup->GLArrayVertexNormal)\
  {\
   glEnableClientState(GL_VERTEX_ARRAY);\
   glDisableClientState(GL_COLOR_ARRAY);\
   glDisableClientState(GL_NORMAL_ARRAY);\
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);\
   glVertexPointer(3, GL_FLOAT, sizeof(E3dGLShadedVertex), LPolyGroup->GLArrayVertexNormal);\
   glDrawElements(GL_TRIANGLES, LPolyGroup->GLTriangleCount*3, GL_UNSIGNED_INT, LPolyGroup->GLTriangleVertexIndexArray);\
  }\
  else if(LPolyGroup->GLArrayVertexNormalST)\
  {\
   glEnableClientState(GL_VERTEX_ARRAY);\
   glDisableClientState(GL_COLOR_ARRAY);\
   glDisableClientState(GL_NORMAL_ARRAY);\
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);\
   glVertexPointer(3, GL_FLOAT, sizeof(E3dGLShadedSTVertex), LPolyGroup->GLArrayVertexNormalST);\
   glDrawElements(GL_TRIANGLES, LPolyGroup->GLTriangleCount*3, GL_UNSIGNED_INT, LPolyGroup->GLTriangleVertexIndexArray);\
  }\
  else if((mPolyCnt=LPolyGroup->NumOfPolygons)>0)\
  {\
   mPolygon=LPolyGroup->Polygons;\
   do\
   {\
    E3dM_DrawPolygon();\
    mPolygon++;\
   } while(--mPolyCnt);\
  }\
 }\
}


//--------------------------------------------------------
// Draw PolyGroup with constant color and 2DTexture
//--------------------------------------------------------
#define E3dM_DrawPolyGroupConstSolid2DTextured()\
{\
 E3dGLMaterial*		mGLMaterial;\
 E3dPolygon*		mPolygon;\
 E3dITriangle*		mITriangle;\
 E3dTriangleStrip*	mTriangleStrip;\
 E3dVertexNode*		mVertexNode;\
 E3dVertexNode**	mVertexNodeP;\
 unsigned int		mPolyCnt, mPC1,\
			mVC, mVN;\
\
\
 LMaterial=LPolyGroup->DrawingMaterial;\
\
 glDisable(GL_LIGHTING);\
 if(LMaterial->NumOf2DTextures)\
 {\
/* Use a grey Material for textured PolyGroups */\
  mGLMaterial=&(LMaterial->GL2DTextureMaterial);\
/*      mGLMaterial=LPlasterGLMaterial;*/\
\
  E3dM_glColorRGBAp8(mGLMaterial->FlatColor);\
\
  L2DTexture=LMaterial->Textures2D[0];\
\
  glEnable(GL_TEXTURE_2D);\
\
  E3dGLM_Setup2DTexture(L2DTexture);\
\
/* Draw primitives	*/\
  switch(L2DTexture->MappingMethod)\
  {\
   case E3dTXT_ENVIRONMENT_MAP:\
    if((mPolyCnt=LPolyGroup->NumOfTriangleStrips)>0)\
    {\
     glDisable(GL_CULL_FACE);\
     mTriangleStrip=LPolyGroup->TriangleStrips;\
     do\
     {\
      E3dM_DrawTriangleStripVertexNormal();\
      mTriangleStrip++;\
     } while(--mPolyCnt);\
     glEnable(GL_CULL_FACE);\
    }\
    else\
    {\
     if((mPolyCnt=LPolyGroup->NumOfPolygons)>0)\
     {\
      mPolygon=LPolyGroup->Polygons;\
      do\
      {\
       E3dM_DrawPolygonVertexNormal();\
       mPolygon++;\
      } while(--mPolyCnt);\
     }\
    }\
   break;\
\
   default:\
/* Draw primitives	*/\
    if((mPolyCnt=LPolyGroup->NumOfTriangleStrips)>0)\
    {\
     glDisable(GL_CULL_FACE);\
     mTriangleStrip=LPolyGroup->TriangleStrips;\
     do\
     {\
      E3dM_DrawTriangleStripConst2DTextured();\
      mTriangleStrip++;\
     } while(--mPolyCnt);\
     glEnable(GL_CULL_FACE);\
    }\
    else\
    {\
     if((mPolyCnt=LPolyGroup->NumOfPolygons)>0)\
     {\
      mPolygon=LPolyGroup->Polygons;\
      do\
      {\
       E3dM_DrawPolygon2DTextured();\
       mPolygon++;\
      } while(--mPolyCnt);\
     }\
    }\
   break;\
  }\
 }\
 else\
 {\
  mGLMaterial=&(LMaterial->GLMaterial);\
  E3dM_glColorRGBAp8(mGLMaterial->FlatColor);\
  glDisable(GL_TEXTURE_2D);\
/* Draw primitives	*/\
  if((mPolyCnt=LPolyGroup->NumOfTriangleStrips)>0)\
  {\
   glDisable(GL_CULL_FACE);\
   mTriangleStrip=LPolyGroup->TriangleStrips;\
   do\
   {\
    E3dM_DrawTriangleStripConst();\
    mTriangleStrip++;\
   } while(--mPolyCnt);\
   glEnable(GL_CULL_FACE);\
  }\
  else\
  {\
   if((mPolyCnt=LPolyGroup->NumOfPolygons)>0)\
   {\
    mPolygon=LPolyGroup->Polygons;\
    do\
    {\
     E3dM_DrawPolygon();\
     mPolygon++;\
    } while(--mPolyCnt);\
   }\
  }\
 }\
}


//------------------------------------------------
// Draw Shaded PolyGroup
//------------------------------------------------
#define E3dM_DrawPolyGroupShadedSolid()\
{\
\
 E3dGLMaterial*		mGLMaterial;\
 E3dPolygon*		mPolygon;\
 E3dITriangle*		mITriangle;\
 E3dTriangleStrip*	mTriangleStrip;\
 E3dVertexNode*		mVertexNode;\
 E3dVertexNode**	mVertexNodeP;\
 unsigned int		mPolyCnt, mPC1,\
			mVC, mVN;\
\
\
 switch(LMaterial->Type)\
 {\
  case E3dMAT_CONSTANT:\
   mGLMaterial=&(LMaterial->GLMaterial);\
   glDisable(GL_LIGHTING);\
   E3dM_glColorRGBAp8(mGLMaterial->FlatColor);\
\
   E3dM_DrawPolyGroupConstSolid();\
  break;\
\
  case E3dMAT_LAMBERT:\
  case E3dMAT_PHONG:\
  case E3dMAT_BLINN:\
   mGLMaterial=&(LMaterial->GLMaterial);\
   glEnable(GL_LIGHTING);\
   E3d_MaterialDefineGL(mGLMaterial);\
\
   if((mPolyCnt=LPolyGroup->NumOfTriangleStrips)>0)\
   {\
    glDisable(GL_CULL_FACE);\
    mTriangleStrip=LPolyGroup->TriangleStrips;\
    do\
    {\
     E3dM_DrawTriangleStripVertexNormal();\
     mTriangleStrip++;\
    } while(--mPolyCnt);\
    glEnable(GL_CULL_FACE);\
   }\
   else\
   {\
    if(LPolyGroup->GLArrayVertexNormal)\
    {\
     glEnableClientState(GL_VERTEX_ARRAY);\
     glEnableClientState(GL_NORMAL_ARRAY);\
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);\
     glVertexPointer(3, GL_FLOAT, sizeof(E3dGLShadedVertex), LPolyGroup->GLArrayVertexNormal);\
     glNormalPointer(GL_FLOAT, sizeof(E3dGLShadedVertex), (char*)(LPolyGroup->GLArrayVertexNormal)+sizeof(E3dGLCoordinate)*3);\
     glDrawElements(GL_TRIANGLES, LPolyGroup->GLTriangleCount*3, GL_UNSIGNED_INT, LPolyGroup->GLTriangleVertexIndexArray);\
    }\
    else if((mPolyCnt=LPolyGroup->NumOfPolygons)>0)\
    {\
     mPolygon=LPolyGroup->Polygons;\
     if((LPolyGroup->Flags&E3dUSE_VERTEX_NORMALS)==0)\
     {\
      do\
      {\
       MglNormal3v(mPolygon->GLNormal);\
       E3dM_DrawPolygon();\
       mPolygon++;\
      } while(--mPolyCnt);\
     }\
     else\
     {\
      do\
      {\
       E3dM_DrawPolygonVertexNormal();\
       mPolygon++;\
      } while(--mPolyCnt);\
     }\
    }\
   }\
  break;\
 }\
}


//----------------------------------------------------------------
// Draw the selected Polygons on top with blending
//----------------------------------------------------------------
#define E3dM_MesDrawSelectedPolygonsOnTop()\
{\
 E3dPolygon*		mPolygon;\
 E3dITriangle*		mITriangle;\
 E3dVertexNode*		mVertexNode;\
 E3dVertexNode**	mVertexNodeP;\
 unsigned int		mPolyCnt, mPC1,\
			mVC, mVN;\
\
\
 if(LDrawSelectedPolygonsInSolidMode)\
 {\
  glDisable(GL_LIGHTING);\
  glDisable(GL_TEXTURE_2D);\
\
  glEnable(GL_BLEND);glBlendFunc(GL_ONE, GL_ONE);\
  E3dM_glColorRGBAi(LDrawContext->ShadedSelectedPolygonRGBAiColor);\
\
  for(LGC=0;LGC<LGN;LGC++)\
  {\
   LPolyGroup=LPolyGroups[LGC];\
\
   if(LPolyGroup->Visible)\
   {\
    if(LPolyGroup->Selected||((LDisplayModeIn&E3dDF_SELECTED)!=0))\
    {\
     if((mPolyCnt=LPolyGroup->NumOfPolygons)>0)\
     {\
      mPolygon=LPolyGroup->Polygons;\
      do\
      {\
       if(mPolygon->Flags&E3dPolyFlagSELECTED) { E3dM_DrawPolygon(); }\
\
       mPolygon++;\
      } while(--mPolyCnt);\
     }\
    }\
   }\
  }\
 }\
}



#define BWd	0.5\

#define E3dM_DrawBone()\
{\
 E3dModel*	mChildModel=LModel->Child;\
\
 if(mChildModel)\
 {\
  LStart[0]=0.0;\
  LStart[1]=0.0;\
  LStart[2]=0.0;\
\
  LEnd[0]=mChildModel->Translation.X;\
  LEnd[1]=mChildModel->Translation.Y;\
  LEnd[2]=mChildModel->Translation.Z;\
\
  LP0[0]=0.0;LP0[1]=BWd;LP0[2]=0.0;\
  LP1[0]=0.0;LP1[1]=0.0;LP1[2]=-BWd;\
  LP2[0]=0.0;LP2[1]=-BWd;LP2[2]=0.0;\
  LP3[0]=0.0;LP3[1]=0.0;LP3[2]=BWd;\
  LPTop[0]=-BWd;LPTop[1]=0.0;LPTop[2]=0.0;\
\
  glBegin(GL_LINES);\
   MglVertex3v(LP0);MglVertex3v(LEnd);\
   MglVertex3v(LP1);MglVertex3v(LEnd);\
   MglVertex3v(LP2);MglVertex3v(LEnd);\
   MglVertex3v(LP3);MglVertex3v(LEnd);\
\
   MglVertex3v(LP0);MglVertex3v(LPTop);\
   MglVertex3v(LP1);MglVertex3v(LPTop);\
   MglVertex3v(LP2);MglVertex3v(LPTop);\
   MglVertex3v(LP3);MglVertex3v(LPTop);\
\
   MglVertex3v(LP0);MglVertex3v(LP1);\
   MglVertex3v(LP1);MglVertex3v(LP2);\
   MglVertex3v(LP2);MglVertex3v(LP3);\
   MglVertex3v(LP3);MglVertex3v(LP0);\
  glEnd();\
 }\
}





//----------------------------------------
// From DrawMesh.c
//----------------------------------------
extern void	E3d_DrawMeshZWire(E3dMesh* LMesh, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInSolidMode);
extern EBool	E3d_DrawMeshHiddenLine(E3dMesh* LMesh, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext);

extern void	E3d_MeshDrawEdgesAndNormals(E3dMesh* LMesh, EBool LNormalModel, E3dDrawContext* LDrawContext, EBool LDrawMeshVertices, EBool LDrawEdges, unsigned int LDisplayModeIn);
extern void	E3d_MeshDrawPolyGroupEdges(E3dMesh* LMesh, EBool LPolyGroupSelected);
extern void	E3d_MeshDrawPolyGroupEdgesHighlight(E3dMesh* LMesh, E3dDrawContext* LDrawContext, EcRGBAiColor* LDefaultEdgeRGBAiColor, EBool LPolyGroupSelected);

extern void	E3d_DrawMeshSolid(E3dMesh* LMesh, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInSolidMode);
extern void	E3d_DrawMeshShadedSolid(E3dMesh* LMesh, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInSolidMode);

extern void	E3d_DrawMeshSolidOpaque(E3dMesh* LMesh, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInSolidMode);
extern void	E3d_DrawMeshShadedSolidOpaque(E3dModel* LModel, E3dMesh* LMesh, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInSolidMode);

extern void	E3d_DrawMesh(E3dModel* LModel, E3dMesh* LMesh, int LModelType, GLenum LGLColorBuffer, unsigned int LDisplayMode, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInShadedMode);
extern void	E3d_DrawMeshOpaque(E3dModel* LModel, E3dMesh* LMesh, int LModelType, GLenum LGLColorBuffer, unsigned int LDisplayMode, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInShadedMode);
extern void	E3d_DrawMeshTransparent(E3dModel* LModel, E3dMesh* LMesh, int LModelType, GLenum LGLColorBuffer, unsigned int LDisplayMode, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInShadedMode);
extern void	E3d_DrawMeshTextureProjector(E3dMesh* LMesh, GLenum LGLColorBuffer, unsigned int LDisplayMode, E3dDrawContext* LDrawContext);




/*






extern void	E3d_DrawMesh(E3dModel* LModel, E3dMesh* LMesh, int LModelType, GLenum LGLColorBuffer, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInShadedMode);
extern void	E3d_DrawMeshOpaque(E3dModel* LModel, E3dMesh* LMesh, int LModelType, GLenum LGLColorBuffer, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInShadedMode);
extern void	E3d_DrawMeshTransparent(E3dModel* LModel, E3dMesh* LMesh, int LModelType, GLenum LGLColorBuffer, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInShadedMode);
extern void	E3d_DrawMeshTextureProjector(E3dMesh* LMesh, GLenum LGLColorBuffer, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext);
*/



//----------------------------------------
// From DrawSpline.c
//----------------------------------------
extern void	E3d_DrawSpline(E3dSpline* LSpline, int LSelection, int LModelType, unsigned int LDisplayMode, E3dDrawContext* LDrawContext);
extern void	E3d_DrawFace(E3dFace* LFace, int LModelType, unsigned int LDisplayMode, E3dDrawContext* LDrawContext);


extern void	E3d_DrawPolyGroupShadedSolidTextured(E3dMesh* LMesh, E3dPolyGroup* LPolyGroup, unsigned int LDisplayModeIn, E3dDrawContext* LDrawContext, EBool LDrawSelectedPolygonsInSolidMode);



#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration which encloses file.
#endif

#endif	// _E3DDrawing_h
