Disclamer: Rendering the Coons patch is part of 3D Graphics homework, but finding the normals at a given point isn't. Just curious.

Here's what I got so far:

enter image description here

It's a Coons patch defined by four Hermite curves. I render the Coons patch by making a mesh of triangles from points calculated on the Coons patch.

The surface could look much smoother than it actually is if I could figure out how to get the normal of the patch at any given point, instead of using the normals of the flat triangles.

Now I know that if I have two tangents of the surface at a given point, their cross product will give me what I look for. I also know that, for an Hermite curve in 2D space, finding the tangent means getting the derivative, which is easy if you see Hermite curve as a product of matrixes and the vector (1, t, t^2, t^3); just use this vector instead (0, 1, 2t 3t^2). The normal is just the perpendicular of the tangent then:

enter image description here

But how do I translate that knowledge into finding the two tangents necessary for finding the normal of the Coons patch at a given point? My shaky programmer maths fail me.

EDIT: Here's how I build my Coons patch. Taken at Wikipedia. The 4 curves are Hermites.

Given four space curves c0(s), c1(s), d0(t), d1(t) which meet at four corners c0(0) = d0(0), c0(1) = d1(0), c1(0) = d0(1), c1(1) = d1(1); linear interpolation can be used to interpolate between c0 and c1, that is

$L_c(s,t)=(1-t) c_0(s)+ t c_1(s) $

and between d0, d1

$L_d(s,t)=(1-s) d_0(t)+ s d_1(t) $

producing two ruled surfaces defined on the unit square.

The bilinear interpolation on the four corner points is another surface

$ B(s,t) = c_0(0) (1-s)(1-t) + c_0(1) s(1-t) + c_1(0) (1-s)t + c_1(1) s t. $

A bilinearly blended Coons patch is the surface

$L_c(s,t)+L_d(s,t)-B(s,t). $

  • $\begingroup$ I assume you have 8 triangles that meet at each vertex of your mesh. You could use the average of the 8 normals of these triangles. That will give you nicer shading. $\endgroup$ – bubba Mar 21 '15 at 14:16
  • $\begingroup$ @bubba That's a good idea. Why make it if I can fake it? If it turns out to be too complicated to find tangents on a bilinearly blended Coons patch, I'm taking this approach. $\endgroup$ – lampyridae Mar 21 '15 at 15:30
  • $\begingroup$ Averaging normals gives very smooth results. I've went for that… and I've added Mortenson to my reading todo list :) $\endgroup$ – lampyridae Mar 22 '15 at 12:48

The term "Coons patch" is used to refer to several different surface types in CAGD, unfortunately. It sounds like you're talking about a standard tensor-product bicubic patch, which can be written in Hermite form: $$ \mathbf{S}(u,v) = [1 \; u \; u^2 \; u^3] \cdot \mathbf{M} \cdot [1 \; v \; v^2 \; v^3]^T $$ where $\mathbf{M}$ is a $4 \times 4$ matrix containing corner points, derivative vectors, and "twist" vectors. There's a good description of these creatures in this book by Mortenson.

You can just differentiate the patch equation from above to get partial derivatives: $$ \frac{\partial\mathbf{S}}{\partial u}(u,v) = [0 \; 1 \; 2u \; 3u^2] \cdot \mathbf{M} \cdot [1 \; v \; v^2 \; v^3]^T $$ $$ \frac{\partial\mathbf{S}}{\partial v}(u,v) = [1 \; u \; u^2 \; u^3] \cdot \mathbf{M} \cdot [0 \; 1 \; 2v \; 3v^2]^T $$ Then, as you mentioned, the normal is just the cross product of the partial derivative vectors $$ \mathbf{N}(u,v) = \frac{\partial\mathbf{S}}{\partial u} \times \frac{\partial\mathbf{S}}{\partial v} $$ You should unitize this normal vector before using it in lighting calculations, of course.

Edit: From the modified question, we now know that the Coons patch is actually a bilinearly blended "boolean sum" one: $$ \mathbf{S}(u,v) = \mathbf{L}_c(u,v) + \mathbf{L}_d(u,v) - \mathbf{B}(u,v) $$ The process described above will work on these kinds of patches, too (or on any parametric surface, actually). We just have to compute partial derivatives, again. These are straightforward: $$ \frac{\partial\mathbf{L}_c}{\partial u} = (1-v)\mathbf{c}'_0(u) + v\mathbf{c}'_1(u) $$ $$ \frac{\partial\mathbf{L}_d}{\partial u} = \mathbf{d}_1(v) - \mathbf{d}_0(v) $$ $$ \frac{\partial\mathbf{B}}{\partial u} = (1-v)\big[\mathbf{c}_0(1) - \mathbf{c}_0(0)\big] + v\big[\mathbf{c}_1(1) - \mathbf{c}_1(0)\big] $$ $$ \frac{\partial\mathbf{S}}{\partial u} = \frac{\partial\mathbf{L}_c}{\partial u} + \frac{\partial\mathbf{L}_d}{\partial u} - \frac{\partial\mathbf{B}}{\partial u} $$ And similarly for the partial derivatives with respect to $v$.

  • $\begingroup$ Thanks for your answer! I didn't realize Coons patch refer to different surface types :( I've updated my question to detail how I define my surface. Could I still find normals using this method? $\endgroup$ – lampyridae Mar 21 '15 at 15:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.