char BindTriangle::set(const XY* corner, const XY& at, const XYZ* positions, const XYZ& topos, const float* distance, triangle_bind_info& res) { //res.wei[0] = 1.0f; //res.wei[1] = res.wei[2] = 0.0f; XYZ dto = topos - positions[0]; if(dto.length() > distance[0]*2) return 0; dto = topos - positions[1]; if(dto.length() > distance[1]*2) return 0; dto = topos - positions[2]; if(dto.length() > distance[2]*2) return 0; float f120 = barycentric_coord(corner[1].x, corner[1].y, corner[2].x, corner[2].y, corner[0].x, corner[0].y); float f201 = barycentric_coord(corner[2].x, corner[2].y, corner[0].x, corner[0].y, corner[1].x, corner[1].y); float f012 = barycentric_coord(corner[0].x, corner[0].y, corner[1].x, corner[1].y, corner[2].x, corner[2].y); float alpha, beta, gamma; alpha = barycentric_coord(corner[1].x,corner[1].y, corner[2].x, corner[2].y, at.x, at.y)/f120; if(alpha<0 || alpha>1) return 0; beta = barycentric_coord(corner[2].x, corner[2].y, corner[0].x, corner[0].y, at.x, at.y)/f201; if(beta<0 || beta>1) return 0; gamma = barycentric_coord(corner[0].x, corner[0].y, corner[1].x, corner[1].y, at.x, at.y)/f012; if(gamma<0 || gamma>1) return 0; res.wei[0] = alpha; res.wei[1] = beta; res.wei[2] = gamma; return 1; }
void HairCache::bind() { if(!guide_data || n_samp < 1) return; if(bind_data) delete[] bind_data; bind_data = new triangle_bind_info[n_samp]; if(pNSeg) delete[] pNSeg; pNSeg = new unsigned[n_samp]; for(unsigned i=0; i<n_samp; i++) { // restrict st between 0 - 1 if(ddice[i].coords < 0) ddice[i].coords = 0; if(ddice[i].coords > 1) ddice[i].coords = 1; if(ddice[i].coordt < 0) ddice[i].coordt = 0; if(ddice[i].coordt > 1) ddice[i].coordt = 1; // find the nearest guide XY from(ddice[i].coords, ddice[i].coordt); ValueAndId* idx = new ValueAndId[num_guide]; for(unsigned j=0; j<num_guide; j++) { idx[j].idx = j; XY to(guide_data[j].u, guide_data[j].v); idx[j].val = from.distantTo(to); } QuickSort::sort(idx, 0, num_guide-1); // find closest guider valid in 3D unsigned validid = 0; XYZ pto = pBind[ddice[i].id0]*ddice[i].alpha + pBind[ddice[i].id1]*ddice[i].beta + pBind[ddice[i].id2]*ddice[i].gamma; XYZ dto = pto - guide_data[idx[validid].idx].P[0]; float dist2valid = dto.length(); while(dist2valid > guide_data[idx[validid].idx].radius*2 && validid<num_guide-1) { validid++; dto = pto - guide_data[idx[validid].idx].P[0]; dist2valid = dto.length(); } bind_data[i].wei[0] = 1.f; bind_data[i].wei[1] = bind_data[i].wei[2] = 0.f; bind_data[i].idx[0] = bind_data[i].idx[1] = bind_data[i].idx[2] = idx[validid].idx; if(validid < num_guide-6) { XY corner[3];XYZ pw[3]; float dist[3]; for(unsigned hdl=0; hdl<3; hdl++) { bind_data[i].idx[0] = idx[validid].idx; bind_data[i].idx[1] = idx[validid+1+hdl].idx; bind_data[i].idx[2] = idx[validid+2+hdl].idx; corner[0].x = guide_data[idx[validid].idx].u; corner[1].x = guide_data[idx[validid+1+hdl].idx].u; corner[2].x = guide_data[idx[validid+2+hdl].idx].u; corner[0].y = guide_data[idx[validid].idx].v; corner[1].y = guide_data[idx[validid+1+hdl].idx].v; corner[2].y = guide_data[idx[validid+2+hdl].idx].v; pw[0] = guide_data[idx[validid].idx].P[0]; pw[1] = guide_data[idx[validid+1+hdl].idx].P[0]; pw[2] = guide_data[idx[validid+2+hdl].idx].P[0]; dist[0] = guide_data[idx[validid].idx].radius; dist[1] = guide_data[idx[validid+1+hdl].idx].radius; dist[2] = guide_data[idx[validid+2+hdl].idx].radius; if( BindTriangle::set(corner, from, pw, pto, dist, bind_data[i]) ) hdl = 4; else bind_data[i].idx[0] = bind_data[i].idx[1] = bind_data[i].idx[2] = idx[validid].idx; } } pNSeg[i] = guide_data[bind_data[i].idx[0]].num_seg;// * bind_data[i].wei[0] + guide_data[bind_data[i].idx[1]].num_seg * bind_data[i].wei[1] + guide_data[bind_data[i].idx[2]].num_seg * bind_data[i].wei[2]; delete[] idx; } }