NURBS bias function undefined

Started by
1 comment, last by Specialist 19 years, 3 months ago
Hi, I'm trying to implement a NURBS class for my game and I can't seem to get the bias function to compute properly. It keeps running into a division by zero error.

class SomeNurbClass
{
	float * k; // knot define somewhere
	...
};

...
float SomeNurbClass::bias(int i, int d, float t)
{// i = sigma index, d = degree, t = time
	if (d == 0)
		return k < t && t < k[i+1] ? 1 : 0;
	
	cout << (t-k) << " / " << (k[i+d-1]-k) << " * bias + ";
	cout << (k[i+d]-t) << " / " << (k[i+d]-k[i+1]) << " * bias" << endl;

	return (t-k)/(k[i+d-1]-k)*bias(i, d-1, t) +
		(k[i+d]-t)/(k[i+d]-k[i+1])*bias(i+1, d-1, t);
}
Just by looking at this section in the denomintor (k[i+d-1]-k) if those two values in the knot vector are equal it's an error. Is there some restriction I'm missing? btw I'm using control points {x, y, z, w} = {{1,1,1,1},{5,5,5,1},{-5,-5,-5,1},{1,1,1,1}} and knot vector = {0,1,2,3,4,5}. 4 control point and order of 2 -> degree 3. output w/ couts: 0 / 2 * bias + 3 / 2 * bias 0 / 1 * bias + 2 / 1 * bias 0 / 0 * bias + 1 / 0 * bias -1 / 0 * bias + 2 / 0 * bias -1 / 1 * bias + 3 / 1 * bias -1 / 0 * bias + 2 / 0 * bias -2 / 0 * bias + 3 / 0 * bias
Advertisement
Hi. Here's my basis function for a NURBS curve. I've used it many projects, so hopefully it works well. The "u" argument is the parameter variable, i.e what you call "time" I guess. Hope it helps.

float NURBS::Basis(int i, int deg, float u, const vector<float> &knots) {  /* First term, Second term, Denominator */  float ft,st,denom = 0.0;  if(deg==0) {    if(u >= knots && u <= knots[i+1]) return 1.0;    else return 0.0;  }    denom = knots[i+deg]-knots;  if(denom==0.0) ft = 0.0;   else ft = ((u-knots)/denom) * Basis(i,deg-1,u,knots);    denom = knots[i+deg+1]-knots[i+1];  if(denom==0.0) st = 0.0;  else st = ((knots[i+deg+1]-u)/denom) * Basis(i+1,deg-1,u,knots);  return (ft + st);}
Sorry I still can't get it to work. I've tried setting the result to zero when there is a division zero but it's giving a constant value for the output using the basis function you posted.

float control[number][4]; // {x,y,z,w};...void NURBS::evulate(Vector &v, const float time){	float n[3] = {0.0, 0.0, 0.0};	float c, d;	c = d = 0.0;	for (int k = 0; k < number; k++)	{		c = control[k][3] * basis(k, degree, time);		n[0] += c*control[k][0];		n[1] += c*control[k][1];		n[2] += c*control[k][2];		d += c;	}	v[0] = (d == 0) ? 0.0 : n[0] / d;	v[1] = (d == 0) ? 0.0 : n[1] / d;	v[2] = (d == 0) ? 0.0 : n[2] / d;}


I tested the time from 0 to 1 incrementing by 1/4 and get these results which isn't right.

// input
control points = {{1,0,0,1},{2,3,0,1},{3,8,0,1},{4,16,0,1}}
knots = {0,1,2,3,4,5}

// output
time
0 [ x: 0 y: 0 z: 0 ]
0.25 [ x: 1 y: 0 z: 0 ]
0.5 [ x: 1 y: 0 z: 0 ]
0.75 [ x: 1 y: 0 z: 0 ]
1 [ x: 1 y: 0 z: 0 ]

This topic is closed to new replies.

Advertisement