static int strand_segment_recursive(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth) { StrandPoint p; StrandBuffer *buffer= sseg->buffer; float dot, d1[2], d2[2], len1, len2; if (depth == buffer->maxdepth) return 0; p.t= (p1->t + p2->t)*0.5f; strand_eval_point(sseg, &p); strand_project_point(buffer->winmat, buffer->winx, buffer->winy, &p); d1[0]= (p.x - p1->x); d1[1]= (p.y - p1->y); len1= d1[0]*d1[0] + d1[1]*d1[1]; d2[0]= (p2->x - p.x); d2[1]= (p2->y - p.y); len2= d2[0]*d2[0] + d2[1]*d2[1]; if (len1 == 0.0f || len2 == 0.0f) return 0; dot= d1[0]*d2[0] + d1[1]*d2[1]; if (dot*dot > sseg->sqadaptcos*len1*len2) return 0; if (spart) { do_strand_point_project(winmat, zspan, p.co1, p.hoco1, p.zco1); do_strand_point_project(winmat, zspan, p.co2, p.hoco2, p.zco2); } else { #if 0 projectvert(p.co1, winmat, p.hoco1); projectvert(p.co2, winmat, p.hoco2); p.clip1= testclip(p.hoco1); p.clip2= testclip(p.hoco2); #endif } if (!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, p1, &p, depth+1)) strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, &p); if (!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, &p, p2, depth+1)) strand_render(re, sseg, winmat, spart, zspan, totzspan, &p, p2); return 1; }
/* ugly function for halos in panorama */ static int panotestclip(Render *re, bool do_pano, float v[4]) { /* part size (ensure we run RE_parts_clamp first) */ BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx)); BLI_assert(re->party == min_ii(re->r.tiley, re->recty)); if (do_pano == false) { return testclip(v); } else { /* to be used for halos en infos */ float abs4; short c = 0; int xparts = (re->rectx + re->partx - 1) / re->partx; abs4= fabsf(v[3]); if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ else if (v[2]> abs4) c+= 32; if ( v[1]>abs4) c+=4; else if ( v[1]< -abs4) c+=8; abs4*= xparts; if ( v[0]>abs4) c+=2; else if ( v[0]< -abs4) c+=1; return c; } }
void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandSegment *sseg) { StrandBuffer *buffer= sseg->buffer; StrandPoint *p1= &sseg->point1; StrandPoint *p2= &sseg->point2; p1->t= 0.0f; p2->t= 1.0f; strand_eval_point(sseg, p1); strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p1); strand_eval_point(sseg, p2); strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p2); if (spart) { do_strand_point_project(winmat, zspan, p1->co1, p1->hoco1, p1->zco1); do_strand_point_project(winmat, zspan, p1->co2, p1->hoco2, p1->zco2); do_strand_point_project(winmat, zspan, p2->co1, p2->hoco1, p2->zco1); do_strand_point_project(winmat, zspan, p2->co2, p2->hoco2, p2->zco2); } else { #if 0 projectvert(p1->co1, winmat, p1->hoco1); projectvert(p1->co2, winmat, p1->hoco2); projectvert(p2->co1, winmat, p2->hoco1); projectvert(p2->co2, winmat, p2->hoco2); p1->clip1= testclip(p1->hoco1); p1->clip2= testclip(p1->hoco2); p2->clip1= testclip(p2->hoco1); p2->clip2= testclip(p2->hoco2); #endif } if (!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, p1, p2, 0)) strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, p2); }
/* width is calculated in hoco space, to ensure strands are visible */ static int strand_test_clip(float winmat[][4], ZSpan *UNUSED(zspan), float *bounds, float *co, float *zcomp, float widthx, float widthy) { float hoco[4]; int clipflag= 0; projectvert(co, winmat, hoco); /* we compare z without perspective division for segment sorting */ *zcomp= hoco[2]; if (hoco[0]+widthx < bounds[0]*hoco[3]) clipflag |= 1; else if (hoco[0]-widthx > bounds[1]*hoco[3]) clipflag |= 2; if (hoco[1]-widthy > bounds[3]*hoco[3]) clipflag |= 4; else if (hoco[1]+widthy < bounds[2]*hoco[3]) clipflag |= 8; clipflag |= testclip(hoco); return clipflag; }
/* ugly function for halos in panorama */ static int panotestclip(Render *re, int do_pano, float *v) { /* to be used for halos en infos */ float abs4; short c=0; if (do_pano == FALSE) { return testclip(v); } abs4= fabs(v[3]); if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ else if (v[2]> abs4) c+= 32; if ( v[1]>abs4) c+=4; else if ( v[1]< -abs4) c+=8; abs4*= re->xparts; if ( v[0]>abs4) c+=2; else if ( v[0]< -abs4) c+=1; return c; }