예제 #1
0
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;
}
예제 #2
0
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;
	}
}