function [x,y,z] = CreateUniformDotsIn3DFrustum(ndots,FOV,aspectr,depthrangen,depthrangef,eyeheight) % [x,y,z] = CreateUniformDotsIn3DFrustum(ndots,FOV,aspectr,depthrangen,depthrangef,eyeheight) % % Sample dots in frustum uniformly, creating a cloud tightly fitting in the % frustum. When the optional 6th parameter eyeheight is given, dots will be % uniformly sampled on a ground plane at -eyeheight. % % z is not sampled from a uniform distribution, but from a parabolic % distribution as the area of cross sections of the frustum is a quadratic % function of the depth plane's depth ( (z*2*tan(FOV/2))^2 * aspectr ) % % Here, I use Inverse transform sampling to transform a uniform random % variable into the quadratic shape random variable % see Luc Devroye. Non-Uniform Random Variate Generation. New York: % Springer-Verlag, 1986. Chapter 2 % (http://cg.scs.carleton.ca/~luc/chapter_two.pdf) % compile following in latex to see full derivation: % ---- % \documentclass[12pt,a4paper]{minimal} % \usepackage{amsmath} % math % % \begin{document} % \textbf{Derivation}:\\ % Use pdf related to cross-section surface of frustum: % $$\left(2 z \tan\left(\frac{FOV}{2}\right)\right)^2 aspectr$$\\ % $$z_1$$ is the distance of the near depth plane\\ % $$z_2$$ is the distance of the far depth plane\\ % $$y$$ is a uniform random variable\\ % Given: $$F(z_2)=1$$ and $$F(z_1)=0$$. % \begin{align} % F(z) &= \int\limits^z_{z_1} k z^2 \, \mathrm{d}z\\ % F(z) &= \frac{k}{3} \left(z^3 - z_1^3\right)\\ % k &= \frac{3}{z_2^3-z_1^3}\\ % F(z) &= \frac{z^3-z_1^3}{z_2^3-z_1^3} % \end{align} % Substitute $$y$$ for $$F(z)$$ and factor out $$z$$: % \begin{align} % z^3 &= y\left(z_2^3-z_1^3\right) + z_1^3\\ % z &= \sqrt[3]{y\left(z_2^3-z_1^3\right) + z_1^3} % \end{align}\\ % For a ground plane, the width of the frustum at depth $$z$$ is given by % $$2 z \tan\left(\frac{FOV}{2}\right) aspectr$$.\\ % By following the same inverse transform sampling steps, we would end up % with % $z = \sqrt{y\left(z_2^2-z_1^2\right) + z_1^2}$ % for the linear distribution between $$z_1$$ and $$z_2$$. % % \end{document} % ---- % 2008 DN Wrote it. % 2009-06-06 DN Changed input check to allow for vector near and far % depthrange and allowed near and far depthrange to be % the same, to place dots at exactly that depth % 2010-06-08 DN Added support for uniform groundplanes psychassert(all(depthrangen<=depthrangef),'Near clipping plane should be closer than far clipping plane'); u = RandLim([1,ndots],0,1); % get uniform random variable if nargin>5 % eye height specified, ground plane z = -(u.*(depthrangef.^2-depthrangen.^2)+depthrangen.^2).^(1/2); % transform to linear distribution (negate as depth postiion is a negative number else % cloud z = -(u.*(depthrangef.^3-depthrangen.^3)+depthrangen.^3).^(1/3); % transform to parabolar distribution (negate as depth postiion is a negative number end yrs = -z*tand(FOV/2); if nargin>5 y = -eyeheight*ones(1,ndots); else y = RandLim([1,ndots],-yrs,yrs); end xrs = yrs * aspectr; x = RandLim([1,ndots],-xrs,xrs); % for a uniform sample over z: % z = -RandLim([1,ndots],depthrangen,depthrangef);