Sign in to follow this  
uncle_rico

Calculating vertex normals for b-spline patches?

Recommended Posts

Hey guys, I've never calculated vertex normals for any mesh. Funny that I should start with b-spline patches! I already have a function written which will take the 16 spline control points and tesselate the patch based on a given number of divisions. The result is a set of triangles which approximate the curve of the patch. In order to light the patch, I need to calculate the normals for each vertex. What method is usually used for spline patches? I suppose I could calculate the normal for each face, and then each vertex normal would be the average normal for each face that shares it. Alternately, I could use the splines themselves. Each vertex represents an intersection between two splines. I could calculate the tangent of each spline at the intersection point, find the vector which is perpendicular to each tangent, and then average them together. Mind you, I have no idea how to implement either solution, but I guess I'll start by asking what solution you guys think would be best?

Share this post


Link to post
Share on other sites
Its is pretty easy to calculate the normals of a b-spline patch, it pretty much falls out of the patch calculation.. Simply calculate the derivative of spline in the U and V direction at that point, then cross product them.

Share this post


Link to post
Share on other sites
I think I can wrap my mind around obtaining the derivative of a curve in 2D space. I took a cursory look at it, and I think I have the general concept down. The way I picture it, the derivative allows me to determine the slope at some arbitrary point along the curve. The slope itself can be represented as a line, which is a tangent to that point.

But in 3D, there are an infinite number of coplanar lanes which are tangent to any point along the curve. So, it seems that the tangent of a 3D curve is a plane. Perhaps, if I could get the normal to that plane, then I would have the vector I'm looking for?

I think it's the multidimensionality of it that I'm confused about.

Share this post


Link to post
Share on other sites
there are 2 ways to do it,

1. Calculate the derivatives in U & V, cross product, normalise, there's your normal.

2. Treat the whole thing as a bunch of tri's, calculate in the same way as for any other polymesh. Typically this is not as accurate, and you may need to manually fix seams on periodic surfaces.

I prefer the 2nd method for real time stuff. The difference in visual quality is only noticeable at low lods (when stuff is typically far away), and it tends to be more efficient and more generic when dealing with some of the more esoteric surface types.


Share this post


Link to post
Share on other sites
Quote:
Original post by uncle_rico
I suppose I could calculate the normal for each face, and then each vertex normal would be the average normal for each face that shares it.


The crap method (that 99.99% of people use - even maya & max) :

memset the normal array to zero

foreach triangle tri in tri_list
n = calculateFaceNormal(tri)
foreach vertex v in tri
v.normal += n;
end
end

foreach normal n in normals
normalise(n)

Share this post


Link to post
Share on other sites
Quote:
Original post by RobTheBloke
Quote:
Original post by uncle_rico
I suppose I could calculate the normal for each face, and then each vertex normal would be the average normal for each face that shares it.


The crap method (that 99.99% of people use - even maya & max) :

memset the normal array to zero

foreach triangle tri in tri_list
n = calculateFaceNormal(tri)
foreach vertex v in tri
v.normal += n;
end
end

foreach normal n in normals
normalise(n)
I'll put in another vote for the above method. I eventually switched all of my procedural mesh generation code over to this method because even though the normals for many shapes (curved surfaces, spheres, cylinders, capsules, ellipsoids, etc.) can be computed directly from the shape definition, it's a pain to write and debug all that extra code, and the general solution usually produces close to the same results. In the end I found it more convenient to have a single ComputeNormals() function that could be used with any input. YMMV though.

Share this post


Link to post
Share on other sites
Consider the middle point here, and assume these form some of the faces of a cube:

___
|\ |
| \ |
|__\|___
|\ |\ |
| \ | \ |
|__\|__\|


The sides where two triangles meet the vertex contribute twice as much to the vertex normal campared to the sides where only one triangle is in contact with it. So I scale each surface normal by the angle of the trangle corner belonging to each vertex, before I add it to it's normal.
That leads to each of the two 45 degree triangle corners contributing half as much as the 90 degree one.

I assume this works better in general too, but I haven't proved that.

Share this post


Link to post
Share on other sites
For a cubic beziers its this (beware of typos :-) ):


float invU=1-u;
float invU2=oneMinusU*oneMinusU;
float u2=u*2;

return (-3*invU2*p0)+3*(invU2-2*u*invU)*p1)+3*(2*u*invU-u2)p2+3*u2*p3;




There is a lot of stuff online.... Here are few links from googling "bezier derivative":
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html
http://www.cs.sunysb.edu/~qin/courses/geometry/4.pdf#search=%22bezier%20derivative%22
http://www.tsunamichannel.com/howto/java/25/index.html

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by uncle_rico

But in 3D, there are an infinite number of coplanar lanes which are tangent to any point along the curve. So, it seems that the tangent of a 3D curve is a plane. Perhaps, if I could get the normal to that plane, then I would have the vector I'm looking for?


The derivative of a 3D curve (C'(u)) at a point P (given by C(u)) is a tangent vector giving the direction of the curve at a given u. At any given point on a patch surface there are two tangent vectors C'(u) and a C'(v), the cross product of these vectors gives your normal.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this