/*****************************************************************************
*   Default polyline/gon drawing routine common to graphics drivers.	     *
*									     *
* Written by:  Gershon Elber				Ver 0.1, June 1993.  *
*****************************************************************************/

#include "irit_sm.h"
#include "iritprsr.h"
#include "cagd_lib.h"
#include "symb_lib.h"
#include "iritgrap.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
* Draw a single Poly object using current modes and transformations.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     A poly object to draw.                                         M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   IGDrawPoly                                                               M
*****************************************************************************/
void IGDrawPoly(IPObjectStruct *PObj)
{
    IPVertexStruct *V;
    IPPolygonStruct
	*Pl = PObj -> U.Pl;

    if (IGGlblAbortKeyPressed)
	return;

    if (IP_IS_POLYLINE_OBJ(PObj)) {
	for (; Pl != NULL; Pl = Pl -> Pnext) {
	    if (Pl -> PVertex != NULL && Pl -> PVertex -> Pnext != NULL) {
		IGMoveTo3D(Pl -> PVertex -> Coord);
		for (V = Pl -> PVertex -> Pnext; V != NULL; V = V -> Pnext)
		    IGLineTo3D(V -> Coord);
	    }
	}
    }
    else if (IP_IS_POINTLIST_OBJ(PObj)) {
	for (; Pl != NULL; Pl = Pl -> Pnext) {
	    for (V = Pl -> PVertex; V != NULL; V = V -> Pnext) {
		int i;
		PointType Ends[6];
		RealType
		    *Pt = V -> Coord;

		for (i = 0; i < 6; i++)
		    PT_COPY(Ends[i], Pt);

		Ends[0][0] -= IG_POINT_WIDTH;
		Ends[1][0] += IG_POINT_WIDTH;
		Ends[2][1] -= IG_POINT_WIDTH;
		Ends[3][1] += IG_POINT_WIDTH;
		Ends[4][2] -= IG_POINT_WIDTH;
		Ends[5][2] += IG_POINT_WIDTH;

		for (i = 0; i < 6; i += 2) {
		    IGMoveTo3D(Ends[i]);
		    IGLineTo3D(Ends[i+1]);
		}
	    }
	}
    }
    else if (IP_IS_POLYGON_OBJ(PObj)) {
	int i, j,
	    NumOfVertices = 0;
	PointType PNormal, VNormal;

	for (; Pl != NULL; Pl = Pl -> Pnext) {
	    IPVertexStruct *PrevV;

	    if (IGGlblBackFaceCull) {
	        RealType P1[3], P2[3];

		MatMultVecby4by4(P1, Pl -> PVertex -> Coord,
				 IGGlblCrntViewMat);
		PT_ADD(PNormal, Pl -> PVertex -> Coord, Pl -> Plane);
		MatMultVecby4by4(P2, PNormal, IGGlblCrntViewMat);
		if (P2[2] - P1[2] > 0.0)
		    continue;
	    }

	    if (IGGlblDrawPNormal) {
		NumOfVertices = 0;
		PNormal[0] = PNormal[1] = PNormal[2] = 0.0;
	    }

	    IGMoveTo3D(Pl -> PVertex -> Coord);
	    for (PrevV = Pl -> PVertex, V = PrevV -> Pnext;
		 V != NULL;
		 PrevV = V, V = V -> Pnext) {
		if (IP_IS_INTERNAL_VRTX(PrevV) && !IGGlblDrawInternal)
		    IGMoveTo3D(V -> Coord);
		else
		    IGLineTo3D(V -> Coord);

		if (IGGlblDrawPNormal) {
		    for (j = 0; j < 3; j++)
			PNormal[j] += V -> Coord[j];
		    NumOfVertices++;
		}
	    }
	    if (!IP_IS_INTERNAL_VRTX(PrevV) || IGGlblDrawInternal)
		IGLineTo3D(Pl -> PVertex -> Coord);

	    if (IGGlblDrawPNormal && IP_HAS_PLANE_POLY(Pl)) {
		for (i = 0; i < 3; i++)
		    PNormal[i] /= NumOfVertices;
		IGMoveTo3D(PNormal);
		for (i = 0; i < 3; i++)
		    PNormal[i] += Pl -> Plane[i] * IGGlblNormalLen;
		IGLineTo3D(PNormal);
	    }

	    if (IGGlblDrawVNormal) {
		for (V = Pl -> PVertex; V != NULL; V = V -> Pnext) {
		    if (IP_HAS_NORMAL_VRTX(V)) {
			for (j = 0; j < 3; j++)
			    VNormal[j] = V -> Coord[j] +
				         V -> Normal[j] * IGGlblNormalLen;
			IGMoveTo3D(V ->Coord);
			IGLineTo3D(VNormal);
		    }
		}
	    }
	}
    }
}
