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; }
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 }
//裁减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++; } }
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); }
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); }
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 } }
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); } } } } }
__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; }
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 */
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; } }
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; }
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 */
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); } }