Пример #1
0
int Circle(HDC hdc, long x, long y, int radius, RECT rc, bool clip, bool fill)
{
  POINT pt[65];
  unsigned int i;

  rectObj rect;
  rect.minx = x-radius;
  rect.maxx = x+radius;
  rect.miny = y-radius;
  rect.maxy = y+radius;
  rectObj rcrect;
  rcrect.minx = rc.left;
  rcrect.maxx = rc.right;
  rcrect.miny = rc.top;
  rcrect.maxy = rc.bottom;

  if (msRectOverlap(&rect, &rcrect)!=MS_TRUE) {
    return FALSE;
  }
  // JMW added faster checking...

  unsigned int step = 1;
  if (radius<20) {
    step = 2;
  }
  for(i=64/step;i--;) {
    pt[i].x = x + (long) (radius * xcoords[i*step]);
    pt[i].y = y + (long) (radius * ycoords[i*step]);
  }
  step = 64/step;
  pt[step].x = x + (long) (radius * xcoords[0]);
  pt[step].y = y + (long) (radius * ycoords[0]);

  if (clip) {
    ClipPolygon(hdc,pt,step+1,rc, fill);
  } else {
    if (fill) {
#ifdef PNA
    if (needclipping==true)
      	ClipPolygon(hdc,pt,step+1,rc, true); // VNT10 090909 fixed bug was false FIX CHECK IF WORKING 
    else
        Polygon(hdc,pt,step+1);
#else
      Polygon(hdc,pt,step+1); 
#endif 
    } else {
// VENTA3 FIX HP clipping bug
#ifdef PNA
      if (needclipping==true)
      	MapWindow::_Polyline(hdc,pt,step+1,rc);
      else
        Polyline(hdc,pt,step+1);
#else
      Polyline(hdc,pt,step+1);
#endif
    }
  }
  return TRUE;
}
Пример #2
0
void MapWindow::_Polyline(HDC hdc, POINT* pt, const int npoints, 
			  const RECT rc) {
#ifdef BUG_IN_CLIPPING
  ClipPolygon(hdc, pt, npoints, rc, false);
  //VENTA2
#elif defined(PNA)
  if (needclipping==true)
    ClipPolygon(hdc, pt, npoints, rc, false);
  else
    Polyline(hdc, pt, npoints);
#else
  Polyline(hdc, pt, npoints);
#endif
}
Пример #3
0
//裁减mesh
void GameFootprint::ClipMesh(long triangleCount, const Triangle *triangle, const D3DXVECTOR3 *vertex, const D3DXVECTOR3 *normal)
{
	D3DXVECTOR3		newVertex[9];
	D3DXVECTOR3		newNormal[9];

	// Clip one triangle at a time
	for (long a = 0; a < triangleCount; a++)
	{
		long i1 = triangle->index[0];
		long i2 = triangle->index[1];
		long i3 = triangle->index[2];

		const D3DXVECTOR3& v1 = vertex[i1];
		const D3DXVECTOR3& v2 = vertex[i2];
		const D3DXVECTOR3& v3 = vertex[i3];

		D3DXVECTOR3 cross;
		D3DXVec3Cross(&cross, &(v2 - v1), &(v3 - v1));
		if (DotProduct(decalNormal, cross) > decalEpsilon * D3DXVec3Length(&cross))
		{
			newVertex[0] = v1;
			newVertex[1] = v2;
			newVertex[2] = v3;

			newNormal[0] = normal[i1];
			newNormal[1] = normal[i2];
			newNormal[2] = normal[i3];

			long count = ClipPolygon(3, newVertex, newNormal, newVertex, newNormal);
			if ((count != 0) && (!AddPolygon(count, newVertex, newNormal))) break;
		}

		triangle++;
	}
}
Пример #4
0
Файл: graph.c Проект: rolk/ug
void NS_DIM_PREFIX UgInversePolygon (COORD_POINT *points, INT n)
{
  INT nout;
  SHORT_POINT out[MAX_POINTS_OF_POLY];

        #ifdef ModelP
  if (me != master)
    return;
        #endif

  if (ClipPolygon(points, n, out, &nout)) return;
  if (nout<2) return;
  (*CurrentOutputDevice->InversePolygon)(out, nout);
}
Пример #5
0
Файл: graph.c Проект: rolk/ug
void NS_DIM_PREFIX UgShadedPolygon (COORD_POINT *points, INT n, DOUBLE intensity)
{
  INT nout;
  SHORT_POINT out[MAX_POINTS_OF_POLY];

        #ifdef ModelP
  if (me != master)
    return;
        #endif

  if (ClipPolygon(points, n, out, &nout)) return;
  if (nout<2) return;
  (*CurrentOutputDevice->ShadedPolygon)(out, nout, intensity);
}
Пример #6
0
void DrawPolygon(float_polygon_type poly)
{
	float_polygon_type poly_out;
	//for (int i = 0; i < poly.n; i++) // Transformação do usuário
	//<Matriz>.DoTransformatio(poly.vertex[i].x, poly.vertex[i].y)
	ClipPolygon(poly, poly_out);
	if (poly_out.n > 0) // resultou em poligono dentro
	{
		polygon_type device_poly;
		device_poly.n = poly_out.n;
		for (int i = 0; i < poly_out.n; i++) // transformacao de janelamento
		{
			ViewingTransformation(&poly_out.vertex[i].x, &poly_out.vertex[i].y);
			NormalizedToDevice(poly_out.vertex[i].x, poly_out.vertex[i].y, &device_poly.vertex[i].x, &device_poly.vertex[i].y);
		}
		DrawPoly(device_poly); // desenha
		//if (fill_polygon)
		//	FillPolygon(poly_out); // preenche poligono
	}
}
Пример #7
0
void UPaperSprite::Triangulate(const FSpritePolygonCollection& Source, TArray<FVector2D>& Target)
{
	Target.Empty();

	for (int32 PolygonIndex = 0; PolygonIndex < Source.Polygons.Num(); ++PolygonIndex)
	{
		const FSpritePolygon& SourcePoly = Source.Polygons[PolygonIndex];
		if (SourcePoly.Vertices.Num() >= 3)
		{
			// Convert our format into one the triangulation library supports
			FClipSMPolygon ClipPolygon(0);
			for (int32 VertexIndex = 0; VertexIndex < SourcePoly.Vertices.Num() ; ++VertexIndex)
			{
				FClipSMVertex* ClipVertex = new (ClipPolygon.Vertices) FClipSMVertex;
				FMemory::Memzero(ClipVertex, sizeof(FClipSMVertex));

				const FVector2D& SourceVertex = SourcePoly.Vertices[VertexIndex];
				ClipVertex->Pos.X = SourceVertex.X;
				ClipVertex->Pos.Z = SourceVertex.Y;
			}
			ClipPolygon.FaceNormal = FVector(0.0f, -1.0f, 0.0f);

			// Attempt to triangulate this polygon
			TArray<FClipSMTriangle> GeneratedTriangles;
			if (TriangulatePoly(/*out*/ GeneratedTriangles, ClipPolygon))
			{
				// Convert the triangles back to our 2D data structure
				for (int32 TriangleIndex = 0; TriangleIndex < GeneratedTriangles.Num(); ++TriangleIndex)
				{
					const FClipSMTriangle& Triangle = GeneratedTriangles[TriangleIndex];

					new (Target) FVector2D(Triangle.Vertices[0].Pos.X, Triangle.Vertices[0].Pos.Z);
					new (Target) FVector2D(Triangle.Vertices[1].Pos.X, Triangle.Vertices[1].Pos.Z);
					new (Target) FVector2D(Triangle.Vertices[2].Pos.X, Triangle.Vertices[2].Pos.Z);
				}
			}
		}
	}
}
Пример #8
0
__regargs UWORD ClipPolygon3D(Point3D *in, Point3D **outp, UWORD n,
                              UWORD clipFlags)
{
  Point3D *out = *outp;

  if (clipFlags) {
#if 0
    if (clipFlags & PF_LEFT) {
      n = ClipPolygon(in, out, n, PF_LEFT);
      swapr(in, out);
    }
    if (clipFlags & PF_TOP) {
      n = ClipPolygon(in, out, n, PF_TOP);
      swapr(in, out);
    }
    if (clipFlags & PF_RIGHT) {
      n = ClipPolygon(in, out, n, PF_RIGHT);
      swapr(in, out);
    }
    if (clipFlags & PF_BOTTOM) {
      n = ClipPolygon(in, out, n, PF_BOTTOM);
      swapr(in, out);
    }
#endif
    if (clipFlags & PF_NEAR) {
      n = ClipPolygon(in, out, n, PF_NEAR);
      swapr(in, out);
    }
    if (clipFlags & PF_FAR) {
      n = ClipPolygon(in, out, n, PF_FAR);
      swapr(in, out);
    }
  }

  *outp = in;
  return n;
}
Пример #9
0
R8 ViewObstructed( VFCTRL *vfCtrl, IX nv1, VERTEX3D v1[], R8 area, IX nDiv )
/* nv1  - number of vertices of surface 1.
 * v1   - vertices of surface 1.
 * area - area of surface 1.
 * nDiv - division factor, 3 or 4. */
  {
  POLY *pp;     /* pointer to a polygon */
  POLY *shade;  /* pointer to the obstruction shadow polygon */
  POLY *stack;  /* pointer to stack of unobstructed polygons */
  POLY *next;   /* pointer to next unobstructed polygons */
  R8 dF,   /* F from a view point to an unshaded area */
    dFv,   /* F from a view point to all unshaded areas */
    AFu;   /* AF from all view points to all unshaded areas */
  VERTEX3D v2[MAXNV2]; /* 3D vertices: obstruction */
  VERTEX3D *pv2; /* clipped obstruction */
  VERTEX2D vs[MAXNV2], vb[MAXNV1]; /* 2D vertices: shadow and base surface (2) */
  SRFDAT3X *srfT;  /* pointer to surface */
  DIRCOS *dc1;  /* pointer to direction cosines of surface 1 */
  R8 xmin, xmax, ymin, ymax; /* clipping limits */
  IX clip; /* if true, clip to prevent upward projection */
  R8 epsDist, epsArea;
  R8 hc, zc[MAXNV1];  /* surface clipping test values */
  VERTEX3D vpt[16];  /* vertices of view points */
  R8 weight[16];     /* integration weighting factors */
  IX nvpt; /* number of view points */
  IX np;   /* view point number */
  IX nv2, nvs, nvb;
  IX j, k, n;

#if( DEBUG > 1 )
  fprintf( _ulog, "ViewObstructed:\n" );
#endif
#if( DEBUG > 2  )
  for( j=0; j<nv1; j++ )
    if( v1[j].z <=0 ) ;
#endif

  dc1 = &vfCtrl->srf1T.dc;
  srfT = &vfCtrl->srf2T;
  nvb = srfT->nv;
  for( n=0; n<nvb; n++ )        /* reverse polygon 2 to clockwise */
    {
    vb[n].x = srfT->v[nvb-1-n].x;
    vb[n].y = srfT->v[nvb-1-n].y;
    }
  xmin = xmax = vb[0].x;
  ymin = ymax = vb[0].y;
  for( n=1; n<nvb; n++ )        /* determine polygon 2 to limits */
    {
    if( vb[n].x < xmin ) xmin = vb[n].x;
    if( vb[n].x > xmax ) xmax = vb[n].x;
    if( vb[n].y < ymin ) ymin = vb[n].y;
    if( vb[n].y > ymax ) ymax = vb[n].y;
    }
#if( DEBUG > 1 )
  DumpP2D( "Base Surface:", nvb, vb );
  fprintf( _ulog, "limits:  %f %f   %f %f\n", xmin, xmax, ymin, ymax );
#endif
  epsDist = 1.0e-6 * sqrt( (xmax-xmin)*(xmax-xmin) + (ymax-ymin)*(ymax-ymin) );
  epsArea = 1.0e-6 * srfT->area;

        /* determine Gaussian weights and view points of polygon 1 */
  nvpt = SubSrf( nDiv, nv1, v1, area, vpt, weight );

        /* compute obstructed view from each view point of polygon 1 */
  for( AFu=0.0,np=0; np<nvpt; np++ )        /* begin view points loop */
    {
    hc = 0.9999f * vpt[np].z;
#if( DEBUG > 1 )
    fprintf( _ulog, "view point: %f %f %f\n", vpt[np].x, vpt[np].y, vpt[np].z );
    fprintf( _ulog, "Hclip %g\n", hc );
    fflush( _ulog );
#endif
        /* begin with cleared small structures area - memBlock */
    InitPolygonMem( epsDist, epsArea );
    stack = SetPolygonHC( nvb, vb, 1.0 );  /* convert surface 2 to HC */
#if( DEBUG > 1 )
    DumpHC( "BASE SURFACE:", stack, NULL );
#endif

        /* project shadow of each view obstructing surface */
    srfT = vfCtrl->srfOT;
    for( dFv=0.0,j=0; j<vfCtrl->nProbObstr; j++,srfT++ )
      {                        /* CTD must be behind surface */
      R8 dot = VDOTW ( (vpt+np), (&srfT->dc) );
#if( DEBUG > 1 )
      fprintf( _ulog, "Surface %d;  dot %f\n", srfT->nr, dot );
      fflush( _ulog );
#endif
      if( dot >= 0.0 ) continue;      /* no shadow polygon created */
      nvs = srfT->nv;
      for( clip=n=0; n<nvs; n++ )
        {
        zc[n] = srfT->v[n].z - hc;
        if( zc[n] > 0.0 ) clip = 1;
        }
      if( clip )        /* clip to prevent upward projection */
        {
#if( DEBUG > 1 )
        fprintf( _ulog, "Clip M;  zc: %g %g %g %g\n",
          zc[0], zc[1], zc[2], zc[3] );
#endif
        nvs = ClipPolygon( -1, nvs, (VERTEX3D *)&srfT->v, zc, v2 );
#if( DEBUG > 0 )
        if( nvs >= MAXNV2 || nvs < 0 ) errorf( 3, __FILE__, __LINE__,
          "Invalid number of vertices: ", IntStr(nvs), "" );
#endif
        if( nvs < 3 ) continue;                /* no shadow polygon created */
        pv2 = v2;
#if( DEBUG > 1 )
        DumpP3D( "Clipped surface:", nvs, pv2 );
#endif
        }
      else
        pv2 = (void *)&srfT->v;

              /* project obstruction from centroid to z=0 plane */
      for( n=0; n<nvs; n++,pv2++ )
        {
        R8 temp = vpt[np].z / (vpt[np].z - pv2->z);  /* projection factor */
        vs[n].x = vpt[np].x - temp * (vpt[np].x - pv2->x);
        vs[n].y = vpt[np].y - temp * (vpt[np].y - pv2->y);
        }
              /* limit projected surface; avoid some HC problems */
#if( DEBUG > 0 )
        if( nvs >= MAXNV2 || nvs < 0 ) errorf( 3, __FILE__, __LINE__,
          "Invalid number of vertices: ", IntStr(nvs), "" );
#endif
      nvs = LimitPolygon( nvs, vs, xmax, xmin, ymax, ymin );
      if( nvs < 3 ) continue;                  /* no shadow polygon created */
#if( DEBUG > 0 )
             /* bounds check on projected surface */
      {
      R8 temp = 0.0;
      for( n=0; n<nvs; n++ )
        {
        if( fabs(vs[n].x) > temp ) temp = fabs(vs[n].x);
        if( fabs(vs[n].y) > temp ) temp = fabs(vs[n].y);
        }
      if( temp > 1.01 ) errorf( 1, __FILE__, __LINE__,
        "Projected surface too large", "" );
      }
#endif
      NewPolygonStack( );
      shade = SetPolygonHC( nvs, vs, 0.0 );
      if( shade )
        {
#if( DEBUG > 1 )
        DumpHC( "SHADOW:", shade, NULL );
#endif

          /* compute unshaded portion of surface 2 polygon */
        NewPolygonStack( );
        for( pp=stack; pp; pp=next ) /* determine portions of old polygons */
          {                          /* outside the shadow polygon. */
          next = pp->next;              /* must save next to pop old stack */
          k = PolygonOverlap( shade, pp, 3, 1 ); /* 1 = popping old stack */
          if( k == -999)
            break;
          }
        if( k == -999)
          stack = NULL;
        else
          stack = TopOfPolygonStack();
        if( stack==NULL )            /* no new unshaded polygons; so */
          break;                     /* polygon 2 is totally obstructed. */

#if( DEBUG > 1 )
        DumpHC( "UNSHADED:", stack, NULL );
#endif
        FreePolygons( shade, NULL ); /* free the shadow polygon */
        }  /* end shade */
      }  /* end of obstruction surfaces (J) loop */
    if( stack == NULL ) continue;

        /* compute interchange area to each unshaded polygon */
    vfCtrl->totVpt += 1;
    for( pp=stack; pp; pp=pp->next )
      {
      vfCtrl->totPoly += 1;
      nv2 = GetPolygonVrt3D( pp, v2 );
#if( DEBUG > 1 )
      DumpP3D( "Unshaded surface:", nv2, v2 );
#endif
      dF = V1AIpart( nv2, v2, vpt+np, dc1 );
#if( DEBUG > 1 )
      fprintf( _ulog, " Partial view factor: %g\n", dF );
#endif
#if( DEBUG > 0 )
      if( dF < 0.0 )
        {
        if( dF < -1.0e-16 )
          {
          errorf( 1, __FILE__, __LINE__,
            "Negative F (", FltStr(dF,4), ") set to 0", "" );
# if( DEBUG > 0 )     /* normally 1 */
          DumpHC( " Polygon", pp, pp );
          fprintf( _ulog, " View point: (%g, %g, %g)\n", vpt[np].x, vpt[np].y, vpt[np].z );
          fprintf( _ulog, " Direction: (%g, %g, %g)\n", dc1->x, dc1->y, dc1->z );
          V1AIpart( nv2, v2, vpt+np, dc1 );
          fflush( _ulog );
# endif
          }
        dF = 0.0;
        }
#endif
      dFv += dF; 
      }

#if( DEBUG > 1 )
    fprintf( _ulog, " SS: x %f, y %f, z %f, dFv %g\n",
      vpt[np].x, vpt[np].y, vpt[np].z, dFv );
#endif
    AFu += dFv * weight[np];
    }  /* end of view points (np) loop */

#if( DEBUG > 0 )
  if( AFu < 0.0 )  // due to negative weight; enly np=0
    {
    if( weight[0] > 0 ) errorf( 1, __FILE__, __LINE__,
//    if( AFu < -1.0e-11 ) errorf( 1, __FILE__, __LINE__,
      "Negative AFu (", FltStr(AFu,4), ") set to 0", "" );
    AFu = 0.0;
    }
#endif

#if( DEBUG > 1 )
  fprintf( _ulog, "v_obst_u AF:  %g\n", AFu );
  fflush( _ulog );
#endif

  return AFu;

  }  /*  end of ViewObstructed  */
Пример #10
0
void Topology::Paint(HDC hdc, RECT rc) {

  if (!shapefileopen) return;

  bool nolabels=false;
  if (scaleCategory==10) {
	// for water areas, use scaleDefault
	if ( MapWindow::zoom.RealScale()>scaleDefaultThreshold) {
		return;
	}
	// since we just checked category 10, if we are over scale we set nolabels
	if ( MapWindow::zoom.RealScale()>scaleThreshold) nolabels=true;
  } else 
  if (MapWindow::zoom.RealScale() > scaleThreshold) return;

  // TODO code: only draw inside screen!
  // this will save time with rendering pixmaps especially
  // checkVisible does only check lat lon , not screen pixels..
  // We need to check also screen.

  HPEN  hpOld;
  HBRUSH hbOld;
  HFONT hfOld;

  if (hPen) {
    hpOld = (HPEN)SelectObject(hdc,  hPen);
    hbOld = (HBRUSH)SelectObject(hdc, hbBrush);
  } else {
    hpOld = NULL;
    hbOld = NULL;
  }
  hfOld = (HFONT)SelectObject(hdc, MapLabelFont);

  // get drawing info
    
  int iskip = 1;
  
  // attempt to bugfix 100615 polyline glitch with zoom over 33Km
  // do not skip points, if drawing coast lines which have a scaleThreshold of 100km!
  // != 5 and != 10
  if (scaleCategory>10) { 
  if (MapWindow::zoom.RealScale()>0.25*scaleThreshold) {
    iskip = 2;
  } 
  if (MapWindow::zoom.RealScale()>0.5*scaleThreshold) {
    iskip = 3;
  }
  if (MapWindow::zoom.RealScale()>0.75*scaleThreshold) {
    iskip = 4;
  }
  }

  // use the already existing screenbounds_latlon, calculated by CalculateScreenPositions in MapWindow2
  rectObj screenRect = MapWindow::screenbounds_latlon;

  static POINT pt[MAXCLIPPOLYGON];
  bool labelprinted=false;

  for (int ixshp = 0; ixshp < shpfile.numshapes; ixshp++) {
    
    XShape *cshape = shpCache[ixshp];

    if (!cshape || cshape->hide) continue;    

    shapeObj *shape = &(cshape->shape);

    switch(shape->type) {


      case(MS_SHAPE_POINT):{

	#if 101016
	// -------------------------- NOT PRINTING ICONS ---------------------------------------------
	bool dobitmap=false;
	if (scaleCategory<90 || (MapWindow::zoom.RealScale()<2)) dobitmap=true;
	// first a latlon overlap check, only approximated because of fastcosine in latlon2screen
	if (checkVisible(*shape, screenRect))
		for (int tt = 0; tt < shape->numlines; tt++) {
			for (int jj=0; jj< shape->line[tt].numpoints; jj++) {
				POINT sc;
				MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc);
				if (dobitmap) {
					// bugfix 101212 missing case for scaleCategory 0 (markers)
					if (scaleCategory==0||cshape->renderSpecial(hdc, sc.x, sc.y,labelprinted)) 
						MapWindow::DrawBitmapIn(hdc, sc, hBitmap,true);
				} else {
					cshape->renderSpecial(hdc, sc.x, sc.y,labelprinted);
				}
			}
		}
	}

	#else
	// -------------------------- PRINTING ICONS ---------------------------------------------
	#if (TOPOFAST)
	// no bitmaps for small town over a certain zoom level and no bitmap if no label at all levels
	bool nobitmap=false, noiconwithnolabel=false;
	if (scaleCategory==90 || scaleCategory==100) {
		noiconwithnolabel=true;
		if (MapWindow::MapScale>4) nobitmap=true;
	}
	#endif

	if (checkVisible(*shape, screenRect))
		for (int tt = 0; tt < shape->numlines; tt++) {
			for (int jj=0; jj< shape->line[tt].numpoints; jj++) {
				POINT sc;
				MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc);
	
				#if (TOPOFAST)
				if (!nobitmap)
				#endif
				#if 101016
				// only paint icon if label is printed too
				if (noiconwithnolabel) {
					if (cshape->renderSpecial(hdc, sc.x, sc.y,labelprinted))
						MapWindow::DrawBitmapIn(hdc, sc, hBitmap,true);
				} else {
					MapWindow::DrawBitmapIn(hdc, sc, hBitmap,true);
					cshape->renderSpecial(hdc, sc.x, sc.y,labelprinted);
				}
				#else
				MapWindow::DrawBitmapIn(hdc, sc, hBitmap,true);
				cshape->renderSpecial(hdc, sc.x, sc.y);
				#endif
			}
		}

	}
	#endif // Use optimized point icons 1.23e
	break;

    case(MS_SHAPE_LINE):

      if (checkVisible(*shape, screenRect))
        for (int tt = 0; tt < shape->numlines; tt ++) {
          
          int minx = rc.right;
          int miny = rc.bottom;
          int msize = min(shape->line[tt].numpoints, MAXCLIPPOLYGON);

	  MapWindow::LatLon2Screen(shape->line[tt].point,
				   pt, msize, 1);
          for (int jj=0; jj< msize; jj++) {
            if (pt[jj].x<=minx) {
              minx = pt[jj].x;
              miny = pt[jj].y;
            }
	  }

          ClipPolygon(hdc, pt, msize, rc, false);
          cshape->renderSpecial(hdc,minx,miny,labelprinted);
        }
      break;
      
    case(MS_SHAPE_POLYGON):

	// if it's a water area (nolabels), print shape up to defaultShape, but print
	// labels only up to custom label levels
	if ( nolabels ) {
		if (checkVisible(*shape, screenRect)) {
			for (int tt = 0; tt < shape->numlines; tt ++) {
				int minx = rc.right;
				int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON);
				MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip);
				for (int jj=0; jj< msize; jj++) {
					if (pt[jj].x<=minx) {
						minx = pt[jj].x;
					}
				}
				ClipPolygon(hdc,pt, msize, rc, true);
			}
		}
	} else 
	if (checkVisible(*shape, screenRect)) {
		for (int tt = 0; tt < shape->numlines; tt ++) {
			int minx = rc.right;
			int miny = rc.bottom;
			int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON);
			MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip);
			for (int jj=0; jj< msize; jj++) {
				if (pt[jj].x<=minx) {
					minx = pt[jj].x;
					miny = pt[jj].y;
				}
			}
			ClipPolygon(hdc,pt, msize, rc, true);
			cshape->renderSpecial(hdc,minx,miny,labelprinted);          
		}
	}
	break;
      
    default:
      break;
    }
  }
Пример #11
0
int RenderFAISector (HDC hdc, const RECT rc , double lat1, double lon1, double lat2, double lon2, int iOpposite , COLORREF fillcolor)
{
float fFAI_Percentage = FAI_NORMAL_PERCENTAGE;

#define N_PLOYGON (3*FAI_SECTOR_STEPS)
double fDist_a, fDist_b, fDist_c, fAngle;
int i;

int iPolyPtr=0;
double lat_d,lon_d;
double alpha, fDistTri, cos_alpha=0;
POINT apSectorPolygon[N_PLOYGON];
POINT Pt1;
DistanceBearing(lat1, lon1, lat2, lon2, &fDist_c, &fAngle);

if(fabs(fDist_c) < 1000.0)  /* distance too short for a FAI sector */
	return -1;

LKASSERT(fFAI_Percentage>0);
double fDistMax = fDist_c/fFAI_Percentage;
LKASSERT(fFAI_Percentage!=0.5);
double fDistMin = fDist_c/(1.0-2.0*fFAI_Percentage);
double fDelta_Dist = 2.0* fDist_c*fFAI_Percentage / (double)(FAI_SECTOR_STEPS);

double dir = -1.0;

  if(fDistMax < FAI_BIG_THRESHOLD)
  {
    fDistMax = fDist_c/FAI_NORMAL_PERCENTAGE;
    fDistMin = fDist_c/(1.0-2.0*FAI_NORMAL_PERCENTAGE);
  }

  if (iOpposite >0)
  {
	dir = 1.0;
  }


  /********************************************************************
   * calc right leg
   ********************************************************************/
  fDelta_Dist =(fDistMax-fDistMin)/ (double)(FAI_SECTOR_STEPS);
  fDistTri = fDistMin;
  if(fDistTri < FAI_BIG_THRESHOLD)
  	fFAI_Percentage = FAI_NORMAL_PERCENTAGE;
  else
	fFAI_Percentage = FAI_NORMAL_PERCENTAGE;
  fDist_a = fDistMin * fFAI_Percentage;
  fDist_b = fDistMin * fFAI_Percentage;
  for(i =0 ;i < FAI_SECTOR_STEPS; i++)
  {
  	LKASSERT(fDist_c*fDist_b!=0);
	cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	alpha = acos(cos_alpha)*180/PI * dir;
	FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);


	MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
    apSectorPolygon[iPolyPtr++] = Pt1;

    fDistTri += fDelta_Dist;
    if(fDistTri < FAI_BIG_THRESHOLD)
      fFAI_Percentage = FAI_NORMAL_PERCENTAGE;
    else
      fFAI_Percentage = FAI_NORMAL_PERCENTAGE;
    fDist_a = fFAI_Percentage * fDistTri;
	fDist_b = fDistTri - fDist_a - fDist_c;
  }

  /********************************************************************
   * calc top leg
   ********************************************************************/
  if(fDistMax < FAI_BIG_THRESHOLD)
    fFAI_Percentage = FAI_NORMAL_PERCENTAGE;
  else
    fFAI_Percentage = FAI_NORMAL_PERCENTAGE;

  fDelta_Dist =  (fDistMax*(1.0-3.0*fFAI_Percentage)) / (double)(FAI_SECTOR_STEPS);
  fDist_a = fDist_c;
  fDist_b = fDistMax - fDist_a - fDist_c;
  for(i =0 ;i < FAI_SECTOR_STEPS; i++)
  {
	LKASSERT(fDist_c*fDist_b!=0);
	cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	alpha = acos(cos_alpha)*180/PI * dir;
	FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);

	MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
    apSectorPolygon[iPolyPtr++] = Pt1;

	fDist_a += fDelta_Dist;
	fDist_b = fDistMax - fDist_a - fDist_c;
  }

  /********************************************************************
   * calc left leg
   ********************************************************************/
  fDelta_Dist =(fDistMax-fDistMin)/ (double)(FAI_SECTOR_STEPS);
  fDistTri = fDistMax;

  fDist_b = fDistMax * fFAI_Percentage;
  fDist_a = fDistTri - fDist_b - fDist_c;
  for(i =0 ;i < FAI_SECTOR_STEPS; i++)
  {
    LKASSERT(fDist_c*fDist_b!=0);
	cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	alpha = acos(cos_alpha)*180/PI * dir;
	FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);

	MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
    apSectorPolygon[iPolyPtr++] = Pt1;

    fDistTri -= fDelta_Dist;
    if(fDistTri < FAI_BIG_THRESHOLD)
      fFAI_Percentage = FAI_NORMAL_PERCENTAGE;
    else
      fFAI_Percentage = FAI_NORMAL_PERCENTAGE;

    fDist_b = fFAI_Percentage * fDistTri;
	fDist_a = fDistTri - fDist_b - fDist_c;
  }

  /********************************************************************
   * draw polygon
   ********************************************************************/
  HPEN   hpSectorPen  = (HPEN)CreatePen(PS_SOLID, IBLSCALE(2),  fillcolor );
  HBRUSH hpSectorFill = NULL;

  HPEN hpOldPen     = (HPEN)  SelectObject(hdc, hpSectorPen);
  HBRUSH hpOldBrush;
/*  if (fillcolor != 0)
  {
	hpSectorFill = (HBRUSH)CreateSolidBrush(fillcolor);
    hpOldBrush = (HBRUSH)SelectObject(hdc, hpSectorFill);
  }
  else */
    hpOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));


  /********************************************/
 // Polygon(hdc, apSectorPolygon,iPolyPtr);
  if (ForcedClipping || DeviceNeedClipping)
    ClipPolygon(hdc,apSectorPolygon,iPolyPtr,rc, true);
  else
    Polygon(hdc,apSectorPolygon,iPolyPtr);
  /********************************************/

  SelectObject(hdc, (HPEN)hpOldPen);
  SelectObject(hdc, (HBRUSH)hpOldBrush);
  DeleteObject(hpSectorPen);
  if(hpSectorFill != NULL)
    DeleteObject(hpSectorFill);



  /********************************************************************
   * calc round leg grid
   ********************************************************************/
  hpSectorPen  = (HPEN)CreatePen(PS_SOLID, (2), RGB_DARKGREY );
  SelectObject(hdc, hpSectorPen);

  double fTic= 1/DISTANCEMODIFY;
  if(fDist_c > 5/DISTANCEMODIFY)   fTic = 10/DISTANCEMODIFY;
  if(fDist_c > 50/DISTANCEMODIFY)  fTic = 25/DISTANCEMODIFY;
  if(fDist_c > 100/DISTANCEMODIFY) fTic = 50/DISTANCEMODIFY;
  if(fDist_c > 200/DISTANCEMODIFY) fTic = 100/DISTANCEMODIFY;
  if(fDist_c > 500/DISTANCEMODIFY) fTic = 250/DISTANCEMODIFY;
  POINT line[2];
  fDistTri = ((int)(fDistMin/fTic)+1) * fTic ;
  HFONT hfOld = (HFONT)SelectObject(hdc, LK8PanelUnitFont);
  int iCnt =0;
  SetTextColor(hdc, RGB_DARKGREY);
  while(fDistTri < fDistMax)
  {
    fDelta_Dist =  (fDistTri-fDistMin)*(1.0-2.0*fFAI_Percentage) / (double)(FAI_SECTOR_STEPS-1);
    fDist_a = fDistTri*fFAI_Percentage;
    fDist_b = fDistTri - fDist_a - fDist_c;
    for(i =0 ;i < FAI_SECTOR_STEPS; i++)
    {
      LKASSERT(fDist_c*fDist_b!=0);
      cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	  alpha = acos(cos_alpha)*180/PI * dir;
	  FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);

	  MapWindow::LatLon2Screen(lon_d, lat_d,  line[0]);

      if(i> 0)
      {
  		ForcedClipping=true;
  		MapWindow::_DrawLine(hdc, PS_DASH, NIBLSCALE(1), line[0] , line[1] , RGB_BLACK, rc);
  		ForcedClipping=false;
      }
	  //  Polyline(hdc, line, 2);

      line[1] =  line[0];
	  fDist_a += fDelta_Dist;
	  fDist_b = fDistTri - fDist_a - fDist_c;

      TCHAR text[180]; SIZE tsize;
      if(iCnt==0)
        _stprintf(text, TEXT("%i%s"), (int)(fDistTri*DISTANCEMODIFY), Units::GetUnitName(Units::GetUserDistanceUnit()));
      else
        _stprintf(text, TEXT("%i"), (int)(fDistTri*DISTANCEMODIFY));
      GetTextExtentPoint(hdc, text, _tcslen(text), &tsize);
      if(i == 0)
        ExtTextOut(hdc, line[0].x, line[0].y, ETO_OPAQUE, NULL, text, _tcslen(text), NULL);

      if(iCnt > 1)
  	    if(i == FAI_SECTOR_STEPS-1)
  	      ExtTextOut(hdc, line[0].x, line[0].y, ETO_OPAQUE, NULL, text, _tcslen(text), NULL);

      if(iCnt > 2)
  	    if((i== (FAI_SECTOR_STEPS/2)))
  	      ExtTextOut(hdc, line[0].x, line[0].y, ETO_OPAQUE, NULL, text, _tcslen(text), NULL);
    }
    iCnt++;
    fDistTri+=fTic;
  }

SelectObject(hdc, hfOld);
SelectObject(hdc, (HPEN)hpOldPen);
DeleteObject( hpSectorPen);
return 0;
}
Пример #12
0
void CoordTrans3D( SRFDAT3D *srf, SRFDATNM *srf1, SRFDATNM *srf2,
  IX *probableObstr, VFCTRL *vfCtrl )
/* srf  - data for all surfaces.
 * xyz  - coordinates of vertices.
 * srf1 - data for surface 1.
 * srf2 - data for surface 2.
 * probableObstr  - list of probable obstructing surfaces.
 * srfT - data for transformed surfaces.
 * scale - coordinate scaling factor.
 */
  {
  VERTEX3D vs[MAXNV1]; /* temporary vertices */
  SRFDAT3X *srf1T;  /* pointer to surface 1 */
  SRFDAT3X *srf2T;  /* pointer to surface 2 */
  SRFDAT3X *srfOT;  /* pointer to obstrucing surface */
  SRFDAT3D *ps;     /* pointer to original surface */
  R8 z[MAXNV1];  /* Z coordinates */
  R8 a[4][4]; /* coordinates transformation matrix */
  R8 b[4][4]; /* coordinate rotation matrix */
  R8 scale; /* coordinate scaling factor */
  R8 zmax;  /* Z coordinate of highest vertex */
  R8 eps=-1.0e-6f;
  IX clip;  /* if true, clip portion of surface below Z=0 plane */
  IX nv;    /* number of vertices */
  IX j, n;

  scale = 1.0f / srf2->rc;   /* distance scaling factor */
#if( DEBUG > 1 )
  fprintf( _ulog, "CoordTrans3D:  %f\n", scale );
  DumpVA( " dc ", 1, 3, &srf2->dc.x );
  DumpVA( " ctd", 1, 3, &srf2->ctd.x );
#endif
        /* set up coordinate transformations */
  CTIdent( b );
  CTRotateU( (void *)&srf2->dc, b );
  CTIdent( a );
  CTShift( (void *)&srf2->ctd, a );
  CTRotateU( (void *)&srf2->dc, a );
  CTScale( scale, a );
#if( DEBUG > 1 )
  DumpVA( " A", 3, 4, a[0] );
  DumpVA( " B", 3, 4, b[0] );
#endif

        /* transform surface 1 */
  srf1T = &vfCtrl->srf1T;
  CT3D( srf1->nv, a, srf1->v, srf1T->v ); /* vertex */
  CT3D( 1, b, (void *)&srf1->dc, (void *)&srf1T->dc );  /* direction cosines */
  CT3D( 1, a, &srf1->ctd, &srf1T->ctd );  /* centroid */
  srf1T->area = srf1->area * scale * scale;
  srf1T->shape = srf1->shape;
  srf1T->nr = srf1->nr;
  srf1T->nv = srf1->nv;

        /* transform surface 2 */
  srf2T = &vfCtrl->srf2T;
  CT3D( srf2->nv, a, srf2->v, srf2T->v );
  CT3D( 1, b, (void *)&srf2->dc, (void *)&srf2T->dc );
  CT3D( 1, a, &srf2->ctd, &srf2T->ctd );
  srf2T->area = srf2->area * scale * scale;
  srf2T->shape = srf2->shape;
  srf2T->nr = srf2->nr;
  srf2T->nv = srf2->nv;
#if( DEBUG > 1 )
  srf1T->dc.w = srf2T->dc.w = 0.0;
  srf1T->ztmax = srf2T->ztmax = 0.0;
#endif

        /* transform obstruction surfaces */
  srfOT = vfCtrl->srfOT;
  for( j=1; j<=vfCtrl->nProbObstr; j++,srfOT++ )
    {
    ps = srf + probableObstr[j];
    srfOT->nr = ps->nr;
    nv = srfOT->nv = ps->nv;
    for( n=0; n<nv; n++ )
      CT3D( 1, a, ps->v[n], srfOT->v+n );  /* vertices */
    CT3D( 1, b, (void *)&ps->dc, (void *)&srfOT->dc );  /* dir. cosines */
    CT3D( 1, a, &ps->ctd, &srfOT->ctd );  /* centroid */
    srfOT->dc.w = -VDOT( (&srfOT->dc), (&srfOT->ctd) );
    zmax = 0.0;   /* zmax and clipping calculations */
    clip = 0;
    for( n=0; n<nv; n++ )
      {
      z[n] = srfOT->v[n].z;
      if( z[n] > zmax )
        zmax = z[n];
      if( z[n] < 0.0 )
        if( z[n] < eps )    /* round-off errors for co-planar srfs */
          clip = 1;
        else
          z[n]=0.0;
      }
    srfOT->ztmax = zmax;
    if( clip )    /* this may never be needed for plane polygons */
      {
#if( DEBUG > 1 )
      fprintf( _ulog, " Clipping obstruction surface %d\n", srfOT->nr );
#endif
      memcpy( vs, srfOT->v, nv*sizeof(VERTEX3D) );
      srfOT->nv = ClipPolygon( 1, nv, vs, z, srfOT->v );
      }
    }

#if( DEBUG > 1 )
  Dump3X( "Surface 1", srf1T );
  Dump3X( "Surface 2", srf2T );
  srfOT = vfCtrl->srfOT;
  for( j=0; j<vfCtrl->nProbObstr; j++,srfOT++ )
    Dump3X( "Obstruction", srfOT );
  fflush( _ulog );
#endif

  }  /*  end of CoordTrans3D  */
Пример #13
0
void AvHSpriteDraw(int spriteHandle, int frame, float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2)
{

    gEngfuncs.pTriAPI->RenderMode(gRenderMode);
    gEngfuncs.pTriAPI->CullFace(TRI_NONE);
    
    struct model_s* spritePtr = (struct model_s*)(gEngfuncs.GetSpritePointer(spriteHandle));
    ASSERT(spritePtr);

    if (!gEngfuncs.pTriAPI->SpriteTexture(spritePtr, frame))
    {
        return;
    }

    Vertex vertex[8];

    vertex[0].x = x1;
    vertex[0].y = y1;
    vertex[0].u = u1;
    vertex[0].v = v1;

    vertex[1].x = x2;
    vertex[1].y = y1;
    vertex[1].u = u2;
    vertex[1].v = v1;

    vertex[2].x = x2;
    vertex[2].y = y2;
    vertex[2].u = u2;
    vertex[2].v = v2;

    vertex[3].x = x1;
    vertex[3].y = y2;
    vertex[3].u = u1;
    vertex[3].v = v2;

    int numVertices = 4;

    float pw = SPR_Width(spriteHandle, frame);
    float ph = SPR_Height(spriteHandle, frame);

    float uOffset = 0;
    float vOffset = 0;

    if (IEngineStudio.IsHardware() == 2)
    {

        // Direct3D addresses textures differently than OpenGL so compensate
        // for that here.

        uOffset = 0.5 / pw;
        vOffset = 0.5 / ph;
  
    }

    // Apply the transformation to the vertices.
    
    for (int i = 0; i < numVertices; ++i)
    {

        if (vertex[i].u < 0.25 / pw)
        {
            vertex[i].u = 0.25 / pw;
        }

        if (vertex[i].v < 0.25 / ph)
        {
            vertex[i].v = 0.25 / ph;
        }

        if (vertex[i].u > 1 - 0.25 / pw)
        {
            vertex[i].u = 1 - 0.25 / pw;
        }

        if (vertex[i].v > 1 - 0.25 / ph)
        {
            vertex[i].v = 1 - 0.25 / ph;
        }

        vertex[i].u += uOffset;
        vertex[i].v += vOffset;
        
        float x = vertex[i].x;
        float y = vertex[i].y;
        
        vertex[i].x = x * gTransform[0][0] + y * gTransform[0][1] + gTransform[0][2];
        vertex[i].y = x * gTransform[1][0] + y * gTransform[1][1] + gTransform[1][2];

    }

    if (gClippingEnabled)
    {
    
        // Clip the polygon to each side of the clipping rectangle. This isn't the
        // fastest way to clip a polygon against a rectangle, but it's probably the
        // simplest.

        ClipPolygon(vertex, numVertices,  1,  0, -gClipRectX1);
        ClipPolygon(vertex, numVertices, -1,  0,  gClipRectX2);
        ClipPolygon(vertex, numVertices,  0,  1, -gClipRectY1);
        ClipPolygon(vertex, numVertices,  0, -1,  gClipRectY2);

    }

    // Compensate for the overbrightening effect.

	float gammaScale = 1.0f / gHUD.GetGammaSlope();
	gEngfuncs.pTriAPI->Color4f(gammaScale * gColor[0], gammaScale * gColor[1], gammaScale * gColor[2], gColor[3]);

    // Output the vertices.

    if (gDrawMode == kSpriteDrawModeFilled)
    {
        gEngfuncs.pTriAPI->Begin(TRI_TRIANGLE_FAN);

        for (int j = 0; j < numVertices; ++j)
        {

            Vector worldPoint;
            
            if (gVGUIEnabled)
            {
                worldPoint.x = (vertex[j].x - gVGUIOffsetX) * gViewportXScale + gViewportXOffset;
                worldPoint.y = (vertex[j].y - gVGUIOffsetY) * gViewportYScale + gViewportYOffset;
                worldPoint.z = 1;
            }
            else
            {
                worldPoint = gViewOrigin +
                    gViewXAxis * vertex[j].x +
                    gViewYAxis * vertex[j].y +
                    gViewZAxis * (gDepth + gDepthOffset);
            }

            gEngfuncs.pTriAPI->TexCoord2f(vertex[j].u, vertex[j].v);
            gEngfuncs.pTriAPI->Vertex3fv((float*)&worldPoint);

        }
    
        gEngfuncs.pTriAPI->End();

    }
    else if (gDrawMode == kSpriteDrawModeBorder)
    {

        gEngfuncs.pTriAPI->Begin(TRI_LINES);

        for (int j = 0; j < numVertices; ++j)
        {

            int k = (j + 1) % numVertices;

            Vector worldPoint1;
            Vector worldPoint2;
            
            if (gVGUIEnabled)
            {

                worldPoint1.x = vertex[j].x - gVGUIOffsetX;
                worldPoint1.y = vertex[j].y - gVGUIOffsetY;
                worldPoint1.z = 1;

                worldPoint2.x = vertex[k].x - gVGUIOffsetX;
                worldPoint2.y = vertex[k].y - gVGUIOffsetY;
                worldPoint2.z = 1;
            
            }
            else
            {
                
                worldPoint1 = gViewOrigin +
                    gViewXAxis * vertex[j].x +
                    gViewYAxis * vertex[j].y +
                    gViewZAxis * (gDepth + gDepthOffset);

                worldPoint2 = gViewOrigin +
                    gViewXAxis * vertex[k].x +
                    gViewYAxis * vertex[k].y +
                    gViewZAxis * (gDepth + gDepthOffset);
            
            }

            gEngfuncs.pTriAPI->TexCoord2f(vertex[j].u, vertex[j].v);
            gEngfuncs.pTriAPI->Vertex3fv((float*)&worldPoint1);

            gEngfuncs.pTriAPI->TexCoord2f(vertex[k].u, vertex[k].v);
            gEngfuncs.pTriAPI->Vertex3fv((float*)&worldPoint2);
        
        }

        gEngfuncs.pTriAPI->End();

    }

    gDepth += kDepthIncrement; 

}
void renderTriangles(const SPVertex * _pVertices, const GLubyte * _pElements, u32 _numElements)
{
	//Current depth buffer can be null if we are loading from a save state
	if(depthBufferList().getCurrent() == nullptr)
		return;

	vertexclip vclip[16];
	vertexi vdraw[12];
	const SPVertex * vsrc[4];
	SPVertex vdata[6];
	for (u32 i = 0; i < _numElements; i += 3) {
		u32 orbits = 0;
		if (_pElements != nullptr) {
			for (u32 j = 0; j < 3; ++j) {
				vsrc[j] = &_pVertices[_pElements[i + j]];
				orbits |= vsrc[j]->clip;
			}
		} else {
			for (u32 j = 0; j < 3; ++j) {
				vsrc[j] = &_pVertices[i + j];
				orbits |= vsrc[j]->clip;
			}
		}
		vsrc[3] = vsrc[0];

		int numVertex = clipW(vsrc, vdata);

		if (!calcScreenCoordinates(vdata, vclip, numVertex))
			continue;

		const int dzdx = ((orbits & CLIP_W) == 0) ? calcDzDx(vclip) : calcDzDx2(vsrc);
		if (dzdx == 0)
			continue;

		if (orbits == 0) {
			assert(numVertex == 3);
			if ((gSP.geometryMode & G_CULL_BACK) != 0) {
				for (int k = 0; k < 3; ++k) {
					vdraw[k].x = floatToFixed16(vclip[k].x);
					vdraw[k].y = floatToFixed16(vclip[k].y);
					vdraw[k].z = floatToFixed16(vclip[k].z);
				}
			} else {
				for (int k = 0; k < 3; ++k) {
					const u32 idx = 3 - k - 1;
					vdraw[k].x = floatToFixed16(vclip[idx].x);
					vdraw[k].y = floatToFixed16(vclip[idx].y);
					vdraw[k].z = floatToFixed16(vclip[idx].z);
				}
			}
		} else {
			vertexclip ** vtx;
			numVertex = ClipPolygon(&vtx, vclip, numVertex);
			if (numVertex < 3)
				continue;

			if ((gSP.geometryMode & G_CULL_BACK) != 0) {
				for (int k = 0; k < numVertex; ++k) {
					vdraw[k].x = floatToFixed16(vtx[k]->x);
					vdraw[k].y = floatToFixed16(vtx[k]->y);
					vdraw[k].z = floatToFixed16(vtx[k]->z);
				}
			} else {
				for (int k = 0; k < numVertex; ++k) {
					const u32 idx = numVertex - k - 1;
					vdraw[k].x = floatToFixed16(vtx[idx]->x);
					vdraw[k].y = floatToFixed16(vtx[idx]->y);
					vdraw[k].z = floatToFixed16(vtx[idx]->z);
				}
			}
		}

		Rasterize(vdraw, numVertex, dzdx);
	}
}