/********************************************************** Pattern and texture module **********************************************************/ #include "qrt.h" #include "pattern.h" /* #define PATTERNDEBUG 1 */ /********************************************************** Given two coordinates on the surface of an object, and a pointer to a colorinfo structure, this routine fills the structure with the objects color info at this location. If the object does not have an associated pattern, its default colorinfo is returned. The routine returns TRUE if the pattern is hit, FALSE otherwise. **********************************************************/ int Find_Color(obj, pattern, loc, cinfo, xmult, ymult) OBJ_PTR obj; PATTERN_PTR pattern; VECT_PTR loc; CINFO_PTR cinfo; float xmult, ymult; { PATTERN_PTR patt; float modpos1, modpos2, pos1, pos2; int modx, mody; if (pattern==NULL) { /* no pattern */ copy_colorinfo(cinfo,&(obj->cinfo)); return(FALSE); } # ifdef ROBUST if (pattern->type != PATT_HEADER) Error(INTERNAL_ERROR,1001); if ((xmult==0) || (ymult==0)) Error(ZERO_MULTIPLIER,1002); # endif /* find object relative position */ (*(ObjData[obj->type].RelPos))(obj,loc,&pos1,&pos2); pos1 /= xmult; /* x and y multipliers */ pos2 /= ymult; /* for pattern sizing */ modx = (int)(pos1 / (pattern->xsize)); if (pos1<0) modx--; mody = (int)(pos2 / (pattern->ysize)); if (pos2<0) mody--; modpos1 = pos1 - ((float)modx * pattern->xsize); modpos2 = pos2 - ((float)mody * pattern->ysize); # ifdef PATTERNDEBUG printf("FINDCOLOR: modpos1,2 = %f %f\n",modpos1, modpos2); printf(" mod x,y = %d %d\n",modx, mody); printf(" mult1,2 = %f %f\n",xmult,ymult); # endif patt = pattern->child; while (patt!=NULL) { THEWORLD.pattern_matches++; if ((*(PattData[patt->type].PattHit))(modpos1, modpos2, patt)) { copy_colorinfo(cinfo,&(patt->cinfo)); return(TRUE); } patt = patt->sibling; } copy_colorinfo(cinfo,&(obj->cinfo)); return(FALSE); } /********************************************************** Determines if point is inside rectangle **********************************************************/ int Rect_Hit(pos1, pos2, patt) float pos1, pos2; PATTERN_PTR patt; { # ifdef PATTERNDEBUG printf("RECT_HIT: sx,y = %f %f\n",patt->startx,patt->starty); printf(" ex,y = %f %f\n",patt->endx,patt->endy); # endif # ifdef ROBUST if (patt->type != RECT_PATTERN) Error(INTERNAL_ERROR,1003); # endif if ( (pos1 > patt->startx) && (pos1 < patt->endx) && (pos2 > patt->starty) && (pos2 < patt->endy) ) return(TRUE); return(FALSE); } /********************************************************** Determines if point is inside circle **********************************************************/ int Circle_Hit(pos1, pos2, patt) float pos1, pos2; PATTERN_PTR patt; { float rad, a, b; # ifdef ROBUST if (patt->type != CIRCLE_PATTERN) Error(INTERNAL_ERROR,1004); # endif a = (pos1 - patt->radius); /* bug in damn compiler */ b = (pos2 - patt->radius); /* we have to break up */ /* long float operations */ rad = sqr(a)+sqr(b); # ifdef PATTERNDEBUG printf("CIRC_HIT\n"); printf(" p1, p2 = %f %f\n",pos1,pos2); printf(" rad = %f\n",patt->radius); printf(" crad = %f\n",rad); # endif if (rad <= sqr(patt->radius)) return(TRUE); return(FALSE); } /********************************************************** Determines if point px, py intersects line x1,y1,x2,y2. Returns true if it does. **********************************************************/ int line_intersect(px, py, x1, y1, x2, y2) float px, py, x1, y1, x2, y2; { float t; x1 -= px; x2 -= px; /* translate line */ y1 -= py; y2 -= py; if ((y1 > 0) && (y2 > 0)) return(FALSE); if ((y1 < 0) && (y2 < 0)) return(FALSE); if ((x1 < 0) && (x2 < 0)) return(FALSE); if (y1 == y2) { if (y1 != 0) return(FALSE); if ((x1 > 0) || (x2 > 0)) return(FALSE); return(TRUE); } t = (-y1) / (y2 - y1); if ((x1 + t * (x2 - x1)) > 0) return(TRUE); return(FALSE); } /********************************************************** Determines if point is inside Polygon **********************************************************/ int Poly_Hit(pos1, pos2, patt) float pos1, pos2; PATTERN_PTR patt; { float xpos, ypos, nxpos, nypos; PATTERN_PTR lseg; int count; # ifdef ROBUST if (patt->type != POLY_PATTERN) Error(INTERNAL_ERROR,1005); # endif lseg = patt->link; if (lseg == NULL) Error(INTERNAL_ERROR,1006); count = 0; while (lseg->link != NULL) { if (line_intersect( pos1, pos2, lseg->startx, lseg->starty, lseg->link->startx, lseg->link->starty) ) count++; lseg = lseg->link; } if ((count % 2) == 0) return(FALSE); return(TRUE); }