NURBS (evaluators)

This topic is 4662 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I am having some problem using the gluNurbsCurve() function The following code works fine , it draw the curves out but once I add more control points and knots. It wont draw anything. Anyone knows does the gluNurbsCurve function limit to only 4 control points? (I want to draw a curve that has 6 control points. GLfloat ctrlpoints[4][3] = { { -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0}, {2.0, -4.0, 0.0}, {4.0, 4.0, 0.0}}; GLfloat knots[8] = { 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 }; GLUnurbsObj* nurbs = gluNewNurbsRenderer(); void display(void) { gluBeginCurve(nurbs); gluNurbsCurve(nurbs, 8, knots, 3, &ctrlpoints[0][0], 4, GL_MAP1_VERTEX_3); gluEndCurve(nurbs); } The following is what I tried to do and wont work: GLfloat ctrlpoints[6][3] = { { 2.4, 0.0, 5.4}, { 1.7, 0.0, 4.8}, {1.6, 0.0, 4.3}, {2.0, 0.0, 4.1}, { 2.7, 0.0, 4.4 }, { 3.3, 0.0, 4.9 }}; GLfloat knots[10] = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; GLUnurbsObj* nurbs = gluNewNurbsRenderer(); void display(void) { gluBeginCurve(nurbs); gluNurbsCurve(nurbs, 10, knots, 3, &ctrlpoints[0][0], 4, GL_MAP1_VERTEX_3); gluEndCurve(nurbs); } Anyone know why?? Thanks

Share on other sites
yup. your knot vector is wrong. This is how to do it, assuming you always want a cubic curve (you probably do), then the order will always be 4 (6th param to gluNurbsCurve).

The number of knots will then be order+num_control_points. So, for 5 points with a curve order of 4, you will require 9 knots :

0 0 0 0 1 2 2 2 2

basically, our order is 4, therefore we require 4 knots at each end to clamp the curve to it's endpoints, so basically write down 4 zeros, and then increment by one until you have 4 left, and fill with the same number. For example, with 6 points your knot vector would need to be :

0 0 0 0 1 2 3 3 3 3

for 7,

0 0 0 0 1 2 3 4 4 4 4

etc etc.

I've got a few examples on my website that don't use the gluNurbs stuff, you might find the examples fairly useful....

Share on other sites
p.s. Maya ignores the first and last knot values!! simply duplicate those values if grabbing the nurbs data from there.

mel curve stuff

you'll prolly want to use the mel command xform -q -ws -t curve1.cp[0] to query the points in world space....

Share on other sites
You are right, I am extracting it from maya. I also found the knot values strange in Maya ((Number of CV + Order (Degree+1) doesn't match the number of knots Maya have)). SOme information I gathered (Rhino websites says the Number of knots should be Control points + degree -1 while opengl says control points + degree + 1)??.
I am trying to replicate the Nurbs model in Opengl (Comparing the Nurbs algorithm with Polygon algorithm (Already done that using Triangles). My comparison will be base on (CPU time for each model and Memory requires for Data (Coordinates etc)) etc.

Anyways is working now, it is to do with the knot. To be honest I still dont understand what the knots do, care to explain please?

Thanks for the Help!!

Share on other sites

Do you know how I can create a NurbsSurface in opengl between those selected four Nurbs Curve?

Share on other sites
Number of CV + Degree + 1 <<--- This is correct!

Maya however ignores the first and last knot value, so it has num cvs + degree - 1. If you read the mel link i posted above it explains all of that.

In a sense knot vector's are a bit of a hack. If you look at the b-spline, clamped b-spline and the Nurbs curve examples on my website they should help explain them a bit (read the notes in each sample in that order).

The knot vector is used specifically with the cox-de-boor algorithm used to generate the curves. Instead of saying :

for each span
for each t value between 0 and 1
calculate point

it's nicer to say

for each t value between 0 and num_spans
calculate point

which is what knot vectors and the cox-de-boor does.

To render the surfaces in openGL, use the birail tools within Maya to create the NURBS surfaces, then export the NURBS data to your own file format, and use the gluNurbsSurface funcs to render.

As i said before, gluNurbs is woefully in-efficient. It's not really that fair to do a NURBS/Poly comparison if you are using gluNurbs to render the primitives. As i mentioned before in a previous thread of yours, if you want any decent speed from NURBS you will have to tesseleate and render the surface yourself.

Basically, the blending functions returned from the cox-de-boor algorithm only need to be re-calculated when the surface LOD changes. Since the cox-de-boor is the most expensive operation associated with NURBS surfaces, caching the result gives you a huge speed imporvement. Also, a tesselated NURBS surface can be rendered with triangle strips, thus making it fast. You also only need to calculate the tex coords and indices for the vertex arrays when the LOD changes too.

As i mentioned before in your previous thread, there is example code on my website to export the data from maya, load it and render it (using the techniques i just described). Advanced Exporter

With your current model, i reackon gluNurbs will give you somewhere between 1->10 fps.

I did a comparison between real time NURBS and polys for my university thesis. Basically, if you are deforming the surface (ie, skinning or blendshapes), then NURBS are faster than polygons (assuming you are not using gluNurbs of course!!). If not, then nurbs may give you some benefit due to variable LOD's.

Share on other sites
I am too doing the comparision for my final year desitation.
I am reading through your websites now and will decide should I use the algorithm or glnurbs.

Is hard to decide, I find it hard to implent the actual algorithm (Dont know where to start at and I cant do maths :-)). My comparision will mainly be focusing on memory usage , how easy is it to model, how accurate it is (which Nurbs is more accurate) and how long does it take to render the model (Not FPS per second, just how long it takes to render the model at the start), I think comparing the FPS will be out of my project scope.

I am comparing it for CAD/Automotive design purposes (Topic is Computer Aided Design, Nurbs Vs Polygons). Why do they use NURBS instead of Polygons when design vehicles etc.

Would you mind to point me to a few sources which have an easy to understand and explanation regarding bizer curves, splines and NURBS?
I have got kind of the idea on what they are, how they works but just missing on the mathematical bit(EG how it calculates the curve etc).
I would really appriciate it :-) and thanks for your help so far.

Edi:
PS
Quote"As i mentioned before in your previous thread, there is example code on my website to export the data from maya, load it and render it (using the techniques i just described). Advanced Exporter"

The techniques do you mean what you described here? -
Quote " Basically, the blending functions returned from the cox-de-boor algorithm only need to be re-calculated when the surface LOD changes. Since the cox-de-boor is the most expensive operation associated with NURBS surfaces, caching the result gives you a huge speed imporvement. Also, a tesselated NURBS surface can be rendered with triangle strips, thus making it fast. You also only need to calculate the tex coords and indices for the vertex arrays when the LOD changes too."

I cant seems to find it, sorry which tutorial on your website you talking about?? Quake 2 MD2 Loaders and Maya Exporter (+ source)??

Thanks a lot for your great help!!

[Edited by - Celesa on April 1, 2005 1:01:12 AM]

Share on other sites
Hi Rob

Got the cox-de-boor algorithm working plus the cache too. As you said, huge performance increase!! I guess saving the CPU to do the calculation everytime the curves is redraw!!

Also I dont know what is causing this problem: http://www.domorewithcel.com/Allroad2.JPG
*Whenever I tries to increment the LOD (level Of Detail), it ends up like that.*

Regarding the Nurbs Surface, Is it true that in order to form a surface between the 4 curves, The two verticals and horizontals curves must have the same number of control points?
This is what I found out:
Eg: The left vertical curve has 10 control points, right vertical curve has 17 control points, upper horizontal curve has 12 control points and buttom curve has 8 control points. Maya will convert the left vertical to have 17 control points and both horizontal to 16 control points.
Do you know how did Maya do that? Algorithm? I do not want to use The maya Libraries in my opengl application, I would like to implement it myself but coudn't find out how it did it.

By The way, I just found out you are from UK. I am in UK too.
I also want to give you credit on helping me out on the implementation of the Nurbs algorithm in my desitation.

Thanks a lot!!

[Edited by - Celesa on April 3, 2005 10:37:00 PM]

Share on other sites
Quote:
 Original post by CelesaHi RobGot the cox-de-boor algorithm working plus the cache too. As you said, huge performance increase!! I guess saving the CPU to do the calculation everytime the curves is redraw!!Also I dont know what is causing this problem: http://www.domorewithcel.com/Allroad2.JPG*Whenever I tries to increment the LOD (level Of Detail), it ends up like that.*

try stepping up in LODS of 2. I don't know why it happens. It's every even LOD of summit like that that is OK.

Quote:
 Regarding the Nurbs Surface, Is it true that in order to form a surface between the 4 curves, The two verticals and horizontals curves must have the same number of control points?This is what I found out:Eg: The left vertical curve has 10 control points, right vertical curve has 17 control points, upper horizontal curve has 12 control points and buttom curve has 8 control points. Maya will convert the left vertical to have 17 control points and both horizontal to 16 control points.Do you know how did Maya do that? Algorithm? I do not want to use The maya Libraries in my opengl application, I would like to implement it myself but coudn't find out how it did it.

I have no idea. Maya's a bit clever like that, but alas all i can determine from Maya is usually via educated guess work. I would assume that life would be much easier having even numbers of points. I have an idea or two about how you could get around the problem, i'd have to have a little play though. On holiday at the moment so don't have my 'tools' with me so to speak....

Quote:
 By The way, I just found out you are from UK. I am in UK too.I also want to give you credit on helping me out on the implementation of the Nurbs algorithm in my desitation.Thanks a lot!!

cheers, send me a copy of the dissertation, i'd be interested to have a read when you're done...

I'd also have a look at the vertex buffer extension if you want to get anymore performance out of it. Use seperate VBO's for the static data and dynamic data. The static stuff can then be stored directly in video mem, and then you only need to send the normal and vertex buffer data down the AGP.

When calculating Normals for the surfaces, ideally you'd use differentiated versions of the curve equations to calculate the tangents of the surface at a given point. I find this method to be a bit slow (there's an example at gamasutra.com optimised for SIMD extensions). I use this method (note the example on my website is actually a bodge)

1. memset the normal array to 0
2. for each polygonal face, calculate face normal via cross product, then normalise face normal.
3. Add the face normal to each vertex normal used by that face.

In theory you should then run over the normals and normalize them. The slightly better method is to normalise them in hardware. You can do this simply by enabling GL_NORMALIZE or within a vertex program. If a given surface direction is periodic, then i simply add the first edges's vertex normals to the second edge's set of normals; I then copy the second set over the first. (If that makes any sense). It just avoids nasty seams along the edges of say a torus or sphere where the surface wraps around.

Also another really subtle optimisation when tesselating the surface is to use if statements before multiplications, ie

if(BlendFunction > 0) {
outpoint += BlendFunction * cv;
}

Since a float comparison is quicker than a multiplication (and since most blend functions returned from the cox-de-boor will be zero, its pointless performing mults when the result will have no effect). I had though that maybe using indexing for the CV's when caching data rather than just storing all blend functions may make the caching slightly less memory heavy. Might be worth a quick test i guess.

i've got a couple of papers i wrote for my masters and ba which i'll try and track down so you've got a couple of extra sources to quote ;)

rob

Share on other sites
great!!! I was looking for some examples of rendering a NURBS patch without using gluNurbs()