<p>I think it's easiest to get the tangent frame by writing the forward mapping from <span class="math-container">$(u,v)$</span> to <span class="math-container">$\mathbf{p}$</span>:
<span class="math-container">$$
    \mathbf{p}(u,v) = \begin{bmatrix} R \, \cos (2\pi u) \\ R \, \sin (2\pi u) \\ vL \end{bmatrix}
$$</span>
Then you can see that the derivatives are:
<span class="math-container">$$
    \frac{\partial\mathbf{p}}{\partial u} = \begin{bmatrix} -2\pi R \, \sin(2\pi u) \\ 2\pi R \, \cos(2\pi u) \\ 0\end{bmatrix} = \begin{bmatrix} -2\pi y \\ 2\pi x \\ 0\end{bmatrix}, \qquad
    \frac{\partial\mathbf{p}}{\partial v} = \begin{bmatrix} 0 \\ 0 \\ L \end{bmatrix}
$$</span>
which matches the pbrt code.</p>
<p>I think your derivation went wrong by assuming that <span class="math-container">$\partial\mathbf{p}/\partial u$</span> was the component-wise reciprocal of <span class="math-container">$\partial u / \partial{\mathbf{p}}$</span>. It's not so simple, because the latter object is really the gradient of <span class="math-container">$u$</span>, where <span class="math-container">$u$</span> is now considered as a scalar field defined over all space (not just on the cylinder). To invert this properly we really need another coordinate running perpendicular to <span class="math-container">$u$</span> in the <span class="math-container">$xy$</span> plane, so that we have a locally invertible mapping; then we can take its Jacobian matrix and invert that. We can use the radius <span class="math-container">$R$</span> as such a coordinate. Then we have the inverse mapping,
<span class="math-container">$$
\begin{aligned}
    u(x,y) &amp;= \frac{1}{2\pi} \arctan(y,x) \\
    R(x,y) &amp;= \sqrt{x^2 + y^2}
\end{aligned}
$$</span>
whose Jacobian is:
<span class="math-container">$$
    \frac{\partial(u,R)}{\partial(x,y)} =
    \begin{bmatrix}
        \tfrac{\partial u}{\partial x} &amp; \tfrac{\partial u}{\partial y} \\
        \tfrac{\partial R}{\partial x} &amp; \tfrac{\partial R}{\partial y}
    \end{bmatrix} =
    \begin{bmatrix}
        -y/(2\pi R^2) &amp; x/(2\pi R^2) \\
        x/R &amp; y/R
    \end{bmatrix}
$$</span>
and the inverse of that is:
<span class="math-container">$$
    \frac{\partial(x,y)}{\partial(u,R)} =
    -2\pi R \begin{bmatrix}
        y/R &amp; -x/(2\pi R^2) \\
        -x/R &amp; -y/(2\pi R^2)
    \end{bmatrix} =
    \begin{bmatrix}
        -2\pi y &amp; x/R \\
        2\pi x &amp; y/R
    \end{bmatrix}
$$</span>
from which you can then read off <span class="math-container">$\partial{(x,y)}/\partial u$</span> as the first column, which matches the result obtained for <span class="math-container">$\partial\mathbf{p}/\partial u$</span> above.</p>

CC BY-SA 4.0
2020-07-11T19:11:52.980Z
2020-07-11T19:11:52.980Z
Nathan Reed
<p>I am new to rendering and I would like to calcualte UV partial derivatives of a cylinder shape, which is parameterized by radius <span class="math-container">$R$</span> and length <span class="math-container">$L$</span>.</p>
<p>Using cylindrical coordinate mapping, for a surface point <span class="math-container">$\mathbf{p}=(x,y,z)$</span>, the UV map (normalized to <span class="math-container">$[0,1]$</span>) is:
<span class="math-container">$$
(u,v) = \Big(\frac{\phi}{2\pi}, \frac{z}{L}\Big)\qquad \text{where} \quad \phi = \arctan \frac{y}{x}
$$</span>
Then I compute the derivatives with respect to <span class="math-container">$\mathbf{p}$</span>, that is:
<span class="math-container">$$
\begin{aligned}
\frac{\partial u}{\partial \mathbf{p}} &amp; = \frac{1}{2\pi R^2} \Big( -y, x, 0\Big) = \frac{1}{2\pi R} \Big( -\sin\phi, \cos\phi, 0\Big)\\
\frac{\partial v}{\partial \mathbf{p}} &amp;= \Big( 0, 0, \frac{1}{L}\Big)
\end{aligned}
$$</span>
Or equivalently:
<span class="math-container">$$
\begin{aligned}
\frac{\partial \mathbf{p}}{\partial u} &amp; = 2\pi R \Big( -\frac{1}{\sin\phi}, \frac{1}{\cos\phi}, 0\Big)\\
\frac{\partial \mathbf{p}}{\partial v} &amp;= \Big( 0, 0, L\Big)
\end{aligned}
$$</span>
Everything looks good until now.</p>
<p><strong>Question</strong></p>
<p>In <a href="https://github.com/mmp/pbrt-v3" rel="nofollow noreferrer">pbrt-3</a>, the relevant part of <a href="https://github.com/mmp/pbrt-v3/blob/9f717d847a807793fa966cf0eaa366852efef167/src/shapes/cylinder.cpp#L105" rel="nofollow noreferrer"><code>cylinder.cpp</code></a> is: (i) UV same as above; (ii) <span class="math-container">$\partial \mathbf{p}/\partial u$</span> however is different:</p>
<pre class="lang-cpp prettyprint-override"><code>Float u = phi / phiMax;
Float v = (pHit.z - zMin) / (zMax - zMin);

// Compute cylinder <span class="math-container">$\dpdu$</span> and <span class="math-container">$\dpdv$</span>
Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0);
Vector3f dpdv(0, 0, zMax - zMin);
</code></pre>
<p>What am I missing here?</p>

<rendering><uv-mapping>
UV partial derivatives of a cylinder shape primitive
WDC
# UV partial derivatives of a cylinder shape primitive

(Asked by: username_0 on 2020-07-11)

I am new to rendering and I would like to calcualte UV partial derivatives of a cylinder shape, which is parameterized by radius $R$ and length $L$.

Using cylindrical coordinate mapping, for a surface point $\mathbf{p}=(x,y,z)$, the UV map (normalized to $[0,1]$) is:
$$
(u,v) = \Big(\frac{\phi}{2\pi}, \frac{z}{L}\Big)\qquad \text{where} \quad \phi = \arctan \frac{y}{x}
$$
Then I compute the derivatives with respect to $\mathbf{p}$, that is:
$$
\begin{aligned}
\frac{\partial u}{\partial \mathbf{p}} & = \frac{1}{2\pi R^2} \Big( -y, x, 0\Big) = \frac{1}{2\pi R} \Big( -\sin\phi, \cos\phi, 0\Big)\\
\frac{\partial v}{\partial \mathbf{p}} &= \Big( 0, 0, \frac{1}{L}\Big)
\end{aligned}
$$
Or equivalently:
$$
\begin{aligned}
\frac{\partial \mathbf{p}}{\partial u} & = 2\pi R \Big( -\frac{1}{\sin\phi}, \frac{1}{\cos\phi}, 0\Big)\\
\frac{\partial \mathbf{p}}{\partial v} &= \Big( 0, 0, L\Big)
\end{aligned}
$$
Everything looks good until now.

**Question**

In [pbrt-3](https://github.com/mmp/pbrt-v3), the relevant part of [`cylinder.cpp`](https://github.com/mmp/pbrt-v3/blob/9f717d847a807793fa966cf0eaa366852efef167/src/shapes/cylinder.cpp#L105) is: (i) UV same as above; (ii) $\partial \mathbf{p}/\partial u$ however is different:

```cpp
Float u = phi / phiMax;
Float v = (pHit.z - zMin) / (zMax - zMin);

// Compute cylinder $\dpdu$ and $\dpdv$
Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0);
Vector3f dpdv(0, 0, zMax - zMin);

```

What am I missing here?

**Tags:** rendering, uv-mapping


---

## 1 answers

### Answer by username_1 on 2020-07-11. Score: 2 | Accepted answer

I think it's easiest to get the tangent frame by writing the forward mapping from $(u,v)$ to $\mathbf{p}$:
$$
\mathbf{p}(u,v) = \begin{bmatrix} R \, \cos (2\pi u) \\ R \, \sin (2\pi u) \\ vL \end{bmatrix}
$$
Then you can see that the derivatives are:
$$
\frac{\partial\mathbf{p}}{\partial u} = \begin{bmatrix} -2\pi R \, \sin(2\pi u) \\ 2\pi R \, \cos(2\pi u) \\ 0\end{bmatrix} = \begin{bmatrix} -2\pi y \\ 2\pi x \\ 0\end{bmatrix}, \qquad
\frac{\partial\mathbf{p}}{\partial v} = \begin{bmatrix} 0 \\ 0 \\ L \end{bmatrix}
$$
which matches the pbrt code.

I think your derivation went wrong by assuming that $\partial\mathbf{p}/\partial u$ was the component-wise reciprocal of $\partial u / \partial{\mathbf{p}}$. It's not so simple, because the latter object is really the gradient of $u$, where $u$ is now considered as a scalar field defined over all space (not just on the cylinder). To invert this properly we really need another coordinate running perpendicular to $u$ in the $xy$ plane, so that we have a locally invertible mapping; then we can take its Jacobian matrix and invert that. We can use the radius $R$ as such a coordinate. Then we have the inverse mapping,
$$
\begin{aligned}
u(x,y) &= \frac{1}{2\pi} \arctan(y,x) \\
R(x,y) &= \sqrt{x^2 + y^2}
\end{aligned}
$$
whose Jacobian is:
$$
\frac{\partial(u,R)}{\partial(x,y)} =
\begin{bmatrix}
\tfrac{\partial u}{\partial x} & \tfrac{\partial u}{\partial y} \\
\tfrac{\partial R}{\partial x} & \tfrac{\partial R}{\partial y}
\end{bmatrix} =
\begin{bmatrix}
-y/(2\pi R^2) & x/(2\pi R^2) \\
x/R & y/R
\end{bmatrix}
$$
and the inverse of that is:
$$
\frac{\partial(x,y)}{\partial(u,R)} =
-2\pi R \begin{bmatrix}
y/R & -x/(2\pi R^2) \\
-x/R & -y/(2\pi R^2)
\end{bmatrix} =
\begin{bmatrix}
-2\pi y & x/R \\
2\pi x & y/R
\end{bmatrix}
$$
from which you can then read off $\partial{(x,y)}/\partial u$ as the first column, which matches the result obtained for $\partial\mathbf{p}/\partial u$ above.


---

