TransWikia.com

UV partial derivatives of a cylinder shape primitive

Computer Graphics Asked by WDC on August 27, 2021

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}{2pi}, 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}{2pi R^2} Big( -y, x, 0Big) = frac{1}{2pi R} Big( -sinphi, cosphi, 0Big)\
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} & = 2pi R Big( -frac{1}{sinphi}, frac{1}{cosphi}, 0Big)\
frac{partial mathbf{p}}{partial v} &= Big( 0, 0, LBig)
end{aligned}
$$

Everything looks good until now.

Question

In pbrt-3, the relevant part of cylinder.cpp is: (i) UV same as above; (ii) $partial mathbf{p}/partial u$ however is different:

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?

One 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 (2pi u) \ R , sin (2pi u) \ vL end{bmatrix} $$ Then you can see that the derivatives are: $$ frac{partialmathbf{p}}{partial u} = begin{bmatrix} -2pi R , sin(2pi u) \ 2pi R , cos(2pi u) \ 0end{bmatrix} = begin{bmatrix} -2pi y \ 2pi x \ 0end{bmatrix}, qquad frac{partialmathbf{p}}{partial v} = begin{bmatrix} 0 \ 0 \ L end{bmatrix} $$ which matches the pbrt code.

I think your derivation went wrong by assuming that $partialmathbf{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}{2pi} 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/(2pi R^2) & x/(2pi R^2) \ x/R & y/R end{bmatrix} $$ and the inverse of that is: $$ frac{partial(x,y)}{partial(u,R)} = -2pi R begin{bmatrix} y/R & -x/(2pi R^2) \ -x/R & -y/(2pi R^2) end{bmatrix} = begin{bmatrix} -2pi y & x/R \ 2pi 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 $partialmathbf{p}/partial u$ above.

Correct answer by Nathan Reed on August 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP