I want to calculate the surface normal to a point on a deformed sphere. The surface of the sphere is displaced along its (original) normals by a function $f(\vec x)$.

In mathematical terms:

Let $\vec x$ be a unit length vector in 3D, i.e. any point on the unit sphere centered on the origin. And let $f:\vec x \to \mathbb{R}$ be a function with a well-defined and continuous gradient $\nabla f(\vec x)$ for every $\vec x$.

Now a point on the surface of the resulting sphere is defined as:

$\vec P(\vec x) = (R + s \cdot f(\vec x)) \cdot \vec x$

where $R$ and $s$ are constants for the radius and the modulation depth, respectively.

The question now: Is this information sufficient to calculate the surface normal to the point $\vec P$? I feel like this should be possible, but it is entirely possible that it is not.

More information:
The function in my case is 3D Simplex Noise which gives values on the range $(-1,1)$ for any $\vec x$. The values for $R$ are about 10 times larger than those of $s$, probably more. Maybe this helps if only an approximation is possible.

Yes, it is possible, though there is still some error in here:

  • Calculate the gradient: $\vec g = \nabla f(\vec x)$
  • Then project it into the tangent plane to the sphere passing through the point: $\vec h = \vec g - (\vec g \cdot \vec x)\vec x$
  • The normal can then be calculated as $\vec n = \vec x - s \cdot \vec h$

This works as long as the radius is $R=1$ and something like $s \ll R$.

I think for $R \ne 1$ the gradient has to be rescaled: $\vec g = \dfrac{1}{R} \nabla f(\vec x)$

But I have no idea why the error gets larger with increasing $s$.

Alright, the rescaling factor was only half complete $\vec g = \dfrac{\nabla f(\vec x)}{R + s \cdot f(\vec x)}$
Now it works for all $R$ and $s$.

Picture of the deformed sphere Here is an image to give some intuition what this thing looks like (with approximated normals).

  • $\begingroup$ What do you mean by "normal to a point". Normal means orthogonal, which requires more than a point. Do you mean the vector connecting the origin to the point? $\endgroup$ – hjhjhj57 Dec 17 '14 at 7:05
  • $\begingroup$ I mean normal to the surface in point P. $\endgroup$ – Gigo Dec 17 '14 at 7:08
  • $\begingroup$ Well, that's a completely different thing ;) $\endgroup$ – hjhjhj57 Dec 17 '14 at 7:13

Let's say that your surface is defined by $\vec{r}(\Theta) = [r_0 + s f(\Theta) ] \hat{r}$, where $\Theta$ represents the spherical angles. I'm going to conjecture that the normal vector in radial coordinates is proportional to $\vec{n} = (-s\nabla f,1)$, where the gradient is a 2-vector in the angle space, and the last component is the radial direction.

We can verify this by making sure the normal vector is orthogonal to the surface. Note that a tangent vector to the surface is $(1,s\nabla f)$. This tangent points along the gradient direction. A normal vector orthogonal to this one points along an isocontour, which by construction is $(\hat{\Theta}^\perp,0)$, where $\hat{\Theta}^\perp$ is 90 degree rotation of the unit angular vectors in the tangent plane to the sphere passing through the point. The dot product with both of these is zero; the first is obvious, while for the second, $\nabla f \cdot \hat{\Theta}^\perp = 0$.

TL;DR: In radial coordinates: $(-s\nabla f,1)$, then just normalize and convert to cartesian if needed.

Elaboration: Based on your comment, it seems that your $f(\vec{x})$ is a scalar function of a 3-vector. Then $\nabla f$ is a 3-vector. The notation I use lumps the spherical coordinates $(\phi,\theta)$ into a single abstract 2-vector-like quantity $\Theta$, so that when you say $f(\Theta)$, that means $f$ is a function of only the spherical coordinate angles (and not a function of radius). Then $\nabla f(\Theta)=\nabla_\Theta f(\Theta)$ is a gradient in this 2-dimensional angle space. Your $\nabla f$ needs to be projected onto the surface of a sphere first, since you only ever sample $f(\vec{x})$ for $\lVert \vec{x} \rVert = 1$.

So, to calculate your normals, given a point $\vec{P}(\vec{x}) = [R + s f(\vec{x})]\vec{x}$ with $\vec{x}$ such that $\lVert \vec{x} \rVert = 1$,

  1. Let $\vec{g}(\vec{x}) = \nabla f(\vec{x})$. Here, $\vec{g}$ is the true gradient of $f$ in 3-space, and you can calculate that in cartesian coordinates, so you get $\vec{g} = (g_x,g_y,g_z)$.
  2. Project out the radial component of $\vec{g}$ to get $\vec{h}(\vec{x})$. To do this, $\vec{h} = \vec{g} - \frac{\vec{g}\cdot\vec{x}}{\vec{x}\cdot\vec{x}}\vec{x}$. Note that the denominator should be 1. Here, $\vec{h}$ represents the component of $\vec{g}$ that should be tangential to a sphere centered at the origin and passing through $\vec{P}$.
  3. An outward normal vector to the surface is $\vec{n} = \vec{x} - s\cdot \vec{h}$. Normalize it to get a unit normal vector.

All these computations can be done in Cartesian coordinates, but notice that I never had to resort to referring to the Cartesian components of any vector; the basic operations are vector arithmetic and dot products.

  • $\begingroup$ Thanks for the answer, but can you elaborate more, especially on the coordinates you use? I'm not quite able to follow your solution. Also $f$ and $\nabla f$ are given in cartesian coordinates and if possible I would like to skip calculating a bunch of angles because trigonometric functions are expensive on the hardware I use for this (GPUs). $\endgroup$ – Gigo Dec 17 '14 at 8:25
  • $\begingroup$ Alright, now I get it, but the radial component of $\vec g$ should be $(\vec g \cdot \vec x)\vec x$ not $(\vec g \cdot \vec x)\vec g$ right? $\endgroup$ – Gigo Dec 17 '14 at 17:56
  • $\begingroup$ @Gigo: Ah yes, you are absolutely right. Fixed. $\endgroup$ – Victor Liu Dec 17 '14 at 18:52
  • $\begingroup$ Strange, there seems to be an error with the sign. If I use $\vec n = \vec x - s \cdot \vec h$ the resulting normal seems correct. $\endgroup$ – Gigo Dec 17 '14 at 21:03
  • $\begingroup$ Well, I guess that makes sense, now that I think about it. The gradient points in the direction of increasing height, so the normal should tilt towards the opposite direction. $\endgroup$ – Gigo Dec 17 '14 at 21:06

Your modulated sphere is the 0-set of the function $$ F(x,y,z)=x^2+y^2+z^2-r^2(x,y,z) \\ F(\rho,\theta,\varphi)=\rho-r(\theta,\varphi) $$ ($r=R+sf$ in your notation). We shall need its differential, $$ dF=2\big((x-rr_x)dx+(y-rr_y)dy+(z-rr_z)dz\big) \\ dF=d\rho-r_\theta d\theta-r_\varphi d\varphi $$ By the definition of the gradient, $\nabla F=(dF)^{\sharp}:\quad \forall v,\;dF(v)=\langle \nabla F, v\rangle=g(\nabla F,v)$. Using the usual Eucledian metric, $$ g=dx^2+dy^2+dz^2 \\ g=d\rho^2+\rho^2d\theta^2+\rho^2\sin^2\theta \;d\varphi^2 $$ we get $$ \nabla F \propto (x-rr_x)\partial_x+(y-rr_y)\partial_y+(z-rr_z)\partial_z \\ \nabla F=\partial_\rho-\tfrac{r_\theta}{\rho^2} \partial_\theta- \tfrac{r_\varphi}{\rho^2\sin^2\theta}\partial_\varphi = \vec e_\rho-\tfrac{r_\theta}{\rho}\vec e_\theta- \tfrac{r_\varphi}{\rho\sin\theta}\vec e_\varphi, $$ where for the spherical coordinates we've written it first in the natural tangent space basis and then in the orthonormal basis used in vector calculus. These expressions evaluated at $F=0$ give a normal vector to the modulated sphere.


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.