% lua-tikz3dtools-doc.tex \DocumentMetadata{ lang = en ,pdfversion = 2.0 ,pdfstandard = {UA-2} } \documentclass[letterpaper]{article} \usepackage{microtype} \usepackage{mathtools} \usepackage{unicode-math} \usepackage{lua-tikz3dtools} \usepackage{bookmark} \title{The \luatikztdtools{} package v2.1.0\\\vspace{.5cm}\tiny{}https://github.com/Pseudonym321/TikZ-Animations/tree/master1/TikZ/lua-tikz3dtools} \author{Jasper} \date{November 22\textsuperscript{nd}, 2025} \begin{document} \maketitle This work is licensed under the \LaTeX{} Project Public License, version 1.3c or later.\par This work was typeset using \TeX{}, the typesetting system created by Donald~E.~Knuth, along with various extensions and packages developed by the \TeX{} community. I am grateful to the vibrant \TeX{} Stack Exchange community for their ongoing support and resources. For those interested, my contributions can be found at \href{https://tex.stackexchange.com/users/319072/jasper}{Jasper} \par \vspace{2em} \hfill\textit{Jasper~Nice} \tableofcontents \section{What the heck is a projective transformation?} Unfortunately, in order to use \luatikztdtools{}, you need to know how to do matrix multiplications. This can be learned in one semester of linear algebra---which is all I currently have. Linear algebra involves linear transformations, which exclude translations and perspective transformations. These linear transformations are encoded in \(3\times3\) matrice (for 3D). This package also uses row-vector convention (because it is more convenient to code with), so our vectors are multiplied on the left of the transformation matrix. Using a homogeneous component, these linear transformation matrices can be transformed into affine and projective transformation matrices. I suggest the mathematical elements for computer graphics book by David Rogers (I recommend the first edition; it is free on archive.org) for learning about projective transformations. Read chapters two and three, and you'll be set. \section{Getting started: drawing a sphere} Before I drown you in documentation, here are some simple diagrams to get you started (see the source for the code): \begin{figure} \centering \begin{tikzpicture} \setobject[ name = {T} ,object = { matrix_multiply( matrix_multiply( euler(pi/3,pi/3,-3*pi/6) ,matrix_multiply( translate(0,0,-2) ,{ {1,0,0,0} ,{0,1,0,0} ,{0,0,1,-1/3} ,{0,0,0,1} } ) ) ,matrix_multiply( xscale(2) ,yscale(2) ) ) } ] \appendsurface[ ustart = {0} ,ustop = {1} ,usamples = {18} ,vstart = {0} ,vstop = {1} ,vsamples = {9} ,transformation = {T} ,x = {sphere(u*tau, v*pi)[1][1]} ,y = {sphere(u*tau, v*pi)[1][2]} ,z = {sphere(u*tau, v*pi)[1][3]} ,fill options = { preaction = { fill = gray!70!white ,fill opacity = 0.7 } ,postaction = { draw = black ,ultra thin ,line cap = round ,line join = round } } ] \appendsolid[ ustart = {-1} ,ustop = {1} ,usamples = {2} ,vstart = {-1} ,vstop = {1} ,vsamples = {2} ,wstart = {-1} ,wstop = {1} ,wsamples = {2} ,transformation = {T} ,x = {u} ,y = {v} ,z = {w} ,fill options = { preaction = { fill = gray!70!white ,fill opacity = 0.1 } ,postaction = { draw = black ,ultra thin ,line cap = round ,line join = round } } ] \displaysegments \end{tikzpicture} \caption{A sphere inside a cube, in perspective} \label{fig:sphere-cube} \end{figure} \begin{figure} \centering \begin{tikzpicture} \pgfmathsetmacro{\param}{0} \setobject[ name = {T} ,object = { matrix_multiply( matrix_multiply( euler(pi/2,pi/4+pi/4*sin(\param),5.25*pi/6+\param) ,translate(0,0,-5) ) ,matrix_multiply( { {1,0,0,0} ,{0,1,0,0} ,{0,0,1,0} ,{0,0,0,1} } ,matrix_multiply(xscale(1/2),yscale(1/2)) ) ) } ] \setobject[ name = {I} ,object = { matrix_inverse(T) } ] \appendsurface[ ustart = {-2} ,ustop = {2} ,usamples = {20} ,vstart = {-2} ,vstop = {2} ,vsamples = {20} ,transformation = {T} ,x = {u} ,y = {v} ,z = {u^4 + v^4 - 4*u*v + 1} ,fill options = { preaction = { fill = green ,fill opacity = 0.2 } ,postaction = { draw = blue ,ultra thin ,line join = round } } ,filter = { abs(matrix_multiply(A,I)[1][3])<2.01 and abs(matrix_multiply(B,I)[1][3])<2.01 and abs(matrix_multiply(C,I)[1][3])<2.01 and abs(matrix_multiply(A,I)[1][2])<2.01 and abs(matrix_multiply(B,I)[1][2])<2.01 and abs(matrix_multiply(C,I)[1][2])<2.01 and abs(matrix_multiply(A,I)[1][1])<2.01 and abs(matrix_multiply(B,I)[1][1])<2.01 and abs(matrix_multiply(C,I)[1][1])<2.01 } ] \appendsolid[ ustart = {-2} ,ustop = {2} ,usamples = {2} ,vstart = {-2} ,vstop = {2} ,vsamples = {2} ,wstart = {-2} ,wstop = {2} ,wsamples = {2} ,transformation = {T} ,x = {u} ,y = {v} ,z = {w} ,fill options = { preaction = { fill = none ,fill opacity = 0.5 } ,postaction = { draw = none ,ultra thin ,line join = round ,line cap = round } } ] \appendcurve[ ustart = {0} ,ustop = {4} ,usamples = {2} ,x = {0} ,y = {0} ,z = {u} ,transformation = {T} ,arrow tip = {true} ,draw options = { draw ,ultra thin ,line cap = round } ] \appendlabel[ x = {0} ,y = {0} ,z = {4.3} ,transformation = {T} ,name = {\(z\)} ] \appendcurve[ ustart = {0} ,ustop = {4} ,usamples = {2} ,x = {0} ,y = {u} ,z = {0} ,transformation = {T} ,arrow tip = {true} ,draw options = { draw ,ultra thin ,line cap = round } ] \appendlabel[ x = {0} ,y = {4.3} ,z = {0} ,transformation = {T} ,name = {\(y\)} ] \appendcurve[ ustart = {0} ,ustop = {4} ,usamples = {2} ,x = {u} ,y = {0} ,z = {0} ,transformation = {T} ,arrow tip = {true} ,draw options = { draw ,ultra thin ,line cap = round } ] \appendlabel[ x = {4.3} ,y = {0} ,z = {0} ,transformation = {T} ,name = {\(x\)} ] \foreach \p in {-4,-3,...,4} { \appendcurve[ ustart = {-4} ,ustop = {4} ,usamples = {2} ,x = {u} ,y = {\p} ,z = {0} ,transformation = {T} ,draw options = { draw = black!70!white ,ultra thin ,line cap = round ,densely dashed } ] \appendcurve[ ustart = {-4} ,ustop = {4} ,usamples = {2} ,x = {\p} ,y = {u} ,z = {0} ,transformation = {T} ,draw options = { draw = black!90!white ,ultra thin ,line cap = round ,densely dashed } ] } \appendsurface[ ustart = {-4} ,ustop = {4} ,usamples = {2} ,vstart = {-4} ,vstop = {4} ,vsamples = {2} ,transformation = {T} ,x = {u} ,y = {v} ,z = {0} ,fill options = { preaction = { fill = gray!70!white ,fill opacity = 0.6 } ,postaction = { draw = none ,ultra thin ,line join = round } } ] \displaysegments \end{tikzpicture} \caption{A case in volving filtering and partitioning} \label{fig:filter-partition} \end{figure} \section{Filtering surfaces: problems and possibilities} Filtering surfaces works when we don't use perspective. Currently, due to a bug, perspective breaks the filtering. I'm open to hear from anyone if they have a fix. Additionally, the partitioning still has a bug due to degenerate triangles, so I'm all ears on that too. \section{Documentation of Commands and Keys} This section summarizes the main commands and configuration keys of the \luatikztdtools{} package. This section is ChatGPT generated, and looks OK to me. \subsection{Setting Objects} \begin{itemize} \item \verb|\setobject[]| Defines a 3D object with a transformation matrix. Options are passed as TikZ keys: \begin{itemize} \item \texttt{name} — Name of the object. \item \texttt{object} — Transformation matrix (default: \texttt{identity\_matrix()}). \end{itemize} \end{itemize} \subsection{Appending Points and Labels} \begin{itemize} \item \verb|\appendpoint[]| Adds a point in 3D space. \begin{itemize} \item \texttt{x, y, z} — Coordinates of the point (default: 0,0,0). \item \texttt{fill options} — TikZ styling for the point (default: \texttt{fill}). \item \texttt{transformation} — Transformation matrix applied to the point (default: identity). \end{itemize} \item \verb|\appendlabel[]| Adds a label at a 3D position. \begin{itemize} \item \texttt{x, y, z} — Coordinates of the label (default: 0,0,0). \item \texttt{name} — Text of the label (default: \texttt{George}). \item \texttt{transformation} — Transformation applied to the label (default: identity). \end{itemize} \end{itemize} \subsection{Appending Curves, Surfaces, and Solids} \begin{itemize} \item \verb|\appendcurve[]| Adds a parametric 3D curve. \begin{itemize} \item \texttt{ustart, ustop} — Parameter range for the curve (default: 0 to 1). \item \texttt{usamples} — Number of samples along the curve (default: 64). \item \texttt{x, y, z} — Parametric functions of the parameter \(u\). \item \texttt{transformation} — Transformation matrix applied to the curve. \item \texttt{draw options} — TikZ styling. \item \texttt{arrow tip/tail, arrow tip/tail options} — Optional arrowheads. \item \texttt{filter} — Boolean or Lua condition for selective drawing. \end{itemize} \item \verb|\appendsurface[]| Adds a parametric 3D surface. \begin{itemize} \item \texttt{ustart, ustop, vstart, vstop} — Parameter ranges. \item \texttt{usamples, vsamples} — Number of samples along \(u\) and \(v\). \item \texttt{x, y, z} — Parametric functions of \(u\) and \(v\). \item \texttt{transformation} — Transformation matrix. \item \texttt{fill options} — TikZ styling for the surface. \item \texttt{filter} — Condition to include/exclude surface points. \end{itemize} \item \verb|\appendsolid[]| Adds a parametric 3D solid (volume). \begin{itemize} \item \texttt{ustart, ustop, vstart, vstop, wstart, wstop} — Parameter ranges. \item \texttt{usamples, vsamples, wsamples} — Sampling resolution. \item \texttt{x, y, z} — Parametric functions of \(u, v, w\). \item \texttt{transformation} — Transformation matrix. \item \texttt{fill options} — TikZ styling for the solid. \item \texttt{filter} — Boolean or Lua condition for selective drawing. \end{itemize} \end{itemize} \subsection{Rendering and Display} \begin{itemize} \item \verb|\displaysegments| Renders all defined objects, curves, surfaces, and solids in proper order, taking occlusion into account. \end{itemize} \subsection{Package Options and Keys} All keys are accessible through Ti\textit{k}Z's path system, under the family \texttt{/lua-tikz3dtools}. Subcategories: \begin{itemize} \item \texttt{/parametric/matrix} — Transformation matrices. \item \texttt{/parametric/point} — Individual points. \item \texttt{/parametric/label} — Labels in 3D space. \item \texttt{/parametric/curve} — Parametric curves. \item \texttt{/parametric/surface} — Parametric surfaces. \item \texttt{/parametric/solid} — Parametric solids. \end{itemize} \section{Matrix Operations and Transformations in Parametric Code} Again, this part is ChatGPT generated. Note that new objects can be made with the \verb|\setobject| command. Inside all parametric fields of \luatikztdtools{} (for instance in \verb|\appendcurve|, \verb|\appendsurface|, and filtering conditions), a small collection of matrix commands is available. These functions originate from the internal module \texttt{mm}, but inside parametric expressions they are used \emph{without} any prefix. All transformations below return \(4\times4\) matrices acting on homogeneous row-vectors \((x,y,z,1)\) using the row-vector convention adopted by the package. \subsection{Core Matrix Operations} \begin{description} \item[\texttt{matrix\_multiply(A,B)}] Computes the product \(A\cdot B\). All chained transformations are formed using this routine. \item[\texttt{matrix\_inverse(A)}] Returns the inverse of a non-singular square matrix using Gauss--Jordan elimination. \end{description} \subsection{Standard 3D Transformations} \begin{description} \item[\texttt{xrotation(angle)}] Rotation about the \(x\)-axis by the given angle. \item[\texttt{yrotation(angle)}] Rotation about the \(y\)-axis. \item[\texttt{zrotation(angle)}] Rotation about the \(z\)-axis. \item[\texttt{euler($\alpha,\beta,\gamma$)}] Returns the composed rotation \[ R_z(\gamma)\,R_y(\beta)\,R_z(\alpha). \] \item[\texttt{translate(x,y,z)}] Translation by the vector \((x,y,z)\). \item[\texttt{xscale(s)}, \texttt{yscale(s)}, \texttt{zscale(s)}] Scaling in the respective coordinate direction. \item[\texttt{scale(s)}] Uniform scaling in all coordinates. \item[\texttt{scale3(x,y,z)}] General non-uniform scaling by three independent factors. \end{description} \medskip These commands can be freely combined using \texttt{matrix\_multiply} to build arbitrary affine (and some projective) transformations directly inside parametric expressions. \end{document}