#include #include #include #include "Common.h" #include "ScratchPad.h" void ScratchPad::configureTriangular(const float gridsz) { double temp; double lu2,lv2,lw2; VECTOR bx,by,bz; VECTOR lcu,lcv; float xmin,xmax,ymin,ymax,xabs,yabs; // Initialise the scratchpad // Edge u in 3D VECTORDIFF(*(patch->vertex[1]->point),*(patch->vertex[0]->point),bx); VECTORCOPY(bx,lcu); // Edge v in 3D VECTORDIFF(*(patch->vertex[2]->point),*(patch->vertex[0]->point),by); VECTORCOPY(by,lcv); // Find z vector VECTORCROSSPRODUCT(bx,by,bz); VECTORNORMALIZE(bz); // Find y vector VECTORNORMALIZE(by); // Find x vector VECTORCROSSPRODUCT(by,bz,bx); // Transform to a 2D problem TRANSFORMVECTOR(lcu,bx,by,cu); TRANSFORMVECTOR(lcv,bx,by,cv); // Rescale the patch for better density estimation xmin = MIN(0.0f,MIN(cu.u,cv.u)); xmax = MAX(0.0f,MAX(cu.u,cv.u)); xabs = fabs(xmax-xmin); ymin = MIN(0.0f,MIN(cu.v,cv.v)); ymax = MAX(0.0f,MAX(cu.v,cv.v)); yabs = fabs(ymax-ymin); if (xabs>yabs) { scalef = xabs/yabs; cu.v *= scalef; cv.v *= scalef; } else { scalef = yabs/xabs;; cu.u *= scalef; cv.u *= scalef; } VEC2DDIFF(cu,cv,cw); // Squared norm lu2 = VEC2DNORM2(cu); lv2 = VEC2DNORM2(cv); lw2 = VEC2DNORM2(cw); // Norm lu = sqrt(lu2); lv = sqrt(lv2); lw = sqrt(lw2); // Calculate altitude length temp = (lu2+lv2-lw2)/(2.0*lu); ihu = 1.0 / sqrt(lv2-(temp*temp)); temp = (lv2+lw2-lu2)/(2.0*lv); ihv = 1.0 / sqrt(lw2-(temp*temp)); temp = (lw2+lu2-lv2)/(2.0*lw); ihw = 1.0 / sqrt(lu2-(temp*temp)); // Find length hmin = 0.5 * MIN(lu,MIN(lv,lw)); hmax = MAX(lu,MAX(lv,lw)); // Choose recursion level chooseRecursionLevel(gridsz); // Scale according to recursion level VEC2DSCALEINVERSE(curnumsubfp,cu,du); VEC2DSCALEINVERSE(curnumsubfp,cv,dv); VEC2DSCALEINVERSE(curnumsubfp,cw,dw); // Record normalised edges VEC2DSCALEINVERSE(lu,cu,nu); VEC2DSCALEINVERSE(lv,cv,nv); VEC2DSCALEINVERSE(lw,cw,nw); // Record opposite of normalised edges VEC2DOPPOSITE(nu,nnu); VEC2DOPPOSITE(nv,nnv); VEC2DOPPOSITE(nw,nnw); ao = 2.0*M_PI / (VEC2DAngle(&nu,&nv)); au = 2.0*M_PI / (VEC2DAngle(&nnw,&nnu)); av = 2.0*M_PI / (VEC2DAngle(&nnv,&nw)); nao = (int)floor(ao) - 1; nau = (int)floor(au) - 1; nav = (int)floor(av) - 1; } void ScratchPad::doReflexTriangular(const VEC2D &orig,const int forbid) { if ( (forbid != 0) && (nreflintersectSegment(origin2d,nu,lu,orig)) { if ((((insideu)&&(reflu>0))||(!insideu)) && (((insideo)&&(reflo>0))||(!insideo))) { VEC2DReflectPointLine(orig,origin2d,nu,refl[nrefl]); nrefl++; if (insideo) reflo--; if (insideu) reflu--; doReflexTriangular(refl[nrefl-1],0); } } } if ((forbid !=1 ) && (nreflintersectSegment(origin2d,nv,lv,orig)) { if ((((insidev)&&(reflv>0))||(!insidev)) && (((insideo)&&(reflo>0))||(!insideo))) { VEC2DReflectPointLine(orig,origin2d,nv,refl[nrefl]); nrefl++; if (insideo) reflo--; if (insidev) reflv--; doReflexTriangular(refl[nrefl-1],1); } } } if ((forbid != 2) && (nreflintersectSegment(cu,nnw,lw,orig)) { if ((((insidev)&&(reflv>0))||(!insidev)) && (((insideu)&&(reflu>0))||(!insideu))) { VEC2DReflectPointLine(orig,cu,nw,refl[nrefl]); nrefl++; if (insideu) reflu--; if (insidev) reflv--; doReflexTriangular(refl[nrefl-1],2); } } } } void ScratchPad::addImpactTriangular(const VEC2D &pos,const COLOR &weight) { int ipos; int u,v,idx,l; int umin,umax,vmin,vmax,wmin,wmax,vmintp,vmaxtp; double wi,tp; double utmin,utmax,vtmin,vtmax,wtmin,wtmax; float ksum; VEC2D delta; COLOR *curcol; // Calculate impact position VEC2DCOMB2(pos.u,cu,pos.v,cv,refl[0]); nrefl++; if (deState.edgeCompensate) { reflo = nao; reflu = nau; reflv = nav; insideo = kernel->isInside(origin2d,refl[0]); insideu = kernel->isInside(cu,refl[0]); insidev = kernel->isInside(cv,refl[0]); doReflexTriangular(refl[0],-1); } // Calculate bounding area tp = kernel->geth()*ihv; utmin = pos.u-tp; utmax = pos.u+tp; tp = kernel->geth()*ihu; vtmin = pos.v-tp; vtmax = pos.v+tp; tp = kernel->geth()*ihw; wi = 1.0-pos.u-pos.v; wtmin = wi-tp; wtmax = wi+tp; // Adjust boundaries (also do the clipping) if (utmin<0.0) umin = 0; else umin = (int)floor(utmin*curnumsubfp)+1; if (utmax>1.0) umax = curnumsub; else umax = (int)ceil(utmax*curnumsubfp)-1; if (vtmin<0.0) vmin = 0; else vmin = (int)floor(vtmin*curnumsubfp)+1; if (vtmax>1.0) vmax = curnumsub; else vmax = (int)ceil(vtmax*curnumsubfp)-1; if (wtmin<0.0) wmin = 0; else wmin = (int)floor(wtmin*curnumsubfp)+1; if (wtmax>1.0) wmax = curnumsub; else wmax = (int)ceil(wtmax*curnumsubfp)-1; // Line per line search l = curnumsub-umin; idx = l*curnumline; for (u=umin;u<=umax;u++) { // Minimum v for this line vmintp = l - wmax; if (vmintpvmax) vmaxtp = vmax; if (vmaxtp>l) vmaxtp = l; // Column per column for (v=vmintp;v<=vmaxtp;v++) { curcol = &(elems[idx+v].rad); VEC2DCOMB2(u,du,v,dv,delta); // Sum all contributions ksum = 0.0f; for (ipos=0;iposevaluate(refl[ipos],delta); // Update the current color if (ksum>EPSILON) { COLORADDSCALED(*curcol,ksum*scalef,weight,*curcol); } } // One line up idx -= curnumline; l--; } } void ScratchPad::iterateOutInTriangular(int (ScratchPad::*functocall)(ScratchPadElement&,ScratchPadElement&,ScratchPadElement&),int recursion) { int deltaline,deltacol,deltashear; int idx,idxcp; int ln,l,j,i; // Prepare for recursion deltaline = (curnumline*curnumsub)>>1; deltacol = (curnumsub)>>1; ln = 1; // Recursion while (recursion != 0) { // Skip the first line idxcp = deltaline; l = 1; deltashear = deltaline+deltacol; // Visit lines 2 by 2 for (j=0;j*functocall)(elems[idx-deltaline],elems[idx+deltaline],elems[idx]); idx += deltacol; /* // o // \ // x <-- calculate this kind of point. // \ // o */ (this->*functocall)(elems[idx-deltashear],elems[idx+deltashear],elems[idx]); idx += deltacol; } idxcp += deltaline; idx = idxcp+deltacol; // Visit an even line for (i=0;i*functocall)(elems[idx-deltacol],elems[idx+deltacol],elems[idx]); idx += 2*deltacol; } idxcp += deltaline; l++; } deltacol >>= 1; deltaline >>= 1; ln <<= 1; recursion--; } } void ScratchPad::iterateInOutTriangular(int (ScratchPad::*functocall)(ScratchPadElement&,ScratchPadElement&,ScratchPadElement&)) { int deltaline,deltacol,deltashear; int numsub; int idx,idxcp; int ln,l,j,i; // Initialisation deltaline = curnumline; deltacol = 1; numsub = (1<>1); // Recursion while (deltacol != numsub) { // Skip the first line idxcp = deltaline; l = 1; deltashear = deltaline+deltacol; // Visit lines 2 by 2 for (j=0;j*functocall)(elems[idx-deltaline],elems[idx+deltaline],elems[idx]); idx += deltacol; /* // o // \ // x <-- calculate this kind of point. // \ // o */ (this->*functocall)(elems[idx-deltashear],elems[idx+deltashear],elems[idx]); idx += deltacol; } idxcp += deltaline; idx = idxcp+deltacol; // Visit an even line for (i=0;i*functocall)(elems[idx-deltacol],elems[idx+deltacol],elems[idx]); idx += 2*deltacol; } idxcp += deltaline; l++; } deltacol <<= 1; deltaline <<= 1; ln >>= 1; } }