\chapter{Introduction}

\section{What this package is for}

Many 3D mathematics illustrations are composed of tessellated parametric
objects.  Once those objects are projected onto the page, the immediate
problem is no longer the 3D object itself but the 2D ordering of the
projected tiles.  If the tiles are drawn in a naive order, the resulting
diagram is often visibly wrong: curves pass through surfaces they ought to go
behind, front faces disappear behind back faces, and labels lose their
geometric clarity.

The purpose of lua-tikz3dtools is to make that class of illustration
practical in Lua\LaTeX{}.  The package extends TikZ with a small set of
commands for appending points, line segments, triangles, labels, curves,
surfaces, solids, and lights to a scene, and then rendering that scene with
occlusion handled in a mathematically coherent way.  In particular, the
package works by reducing the visible geometry to points, line segments, and
triangles, partitioning simplices when necessary, and then sorting them
before they are drawn.  When the resulting occlusion graph contains cycles,
the package detects them through Tarjan's algorithm for strongly connected
components and resolves them by further partitioning the offending triangles.

The algorithms behind this pipeline---a transitive partial order occlusion
comparator for points, line segments, and triangles, and a minimal
partitioning procedure that resolves tiles capable of partitioning one
another---are described in the companion TUGboat
article~\cite{nice2025luatikz3dtools}.  The present manual focuses on the
user-facing interface rather than the internal mathematics.

\section{How the package is meant to be used}

The basic workflow is straightforward.  A scene is built incrementally
inside a TikZ picture.  One may first define reusable objects---such as
matrices or named vectors---with \verb|\setobject|.  One may then append
visible geometry with commands such as \verb|\appendpoint|,
\verb|\appendcurve|, \verb|\appendsurface|, \verb|\appendtriangle|, and
\verb|\appendsolid|.  Lights may be added with \verb|\appendlight|, and
labels with \verb|\appendlabel|.  Once the scene has been assembled,
\verb|\displaysimplices| partitions the geometry where needed, applies user
filters, sorts the resulting simplices by occlusion, and emits the final
TikZ paths.

This means that the order in which objects are appended is not, in general,
the order in which they are drawn.  The package follows a painter's-algorithm
pipeline, but it does so only after placing the geometry into a state where
that ordering is meaningful.  The user should therefore think of the append
commands as describing a scene rather than issuing immediate draw operations.

The expressions supplied to the package are Lua expressions evaluated in a
restricted environment.  Standard mathematical functions are available,
together with the package's \verb|Vector| and \verb|Matrix| types and the
constant \verb|tau|.  This makes it possible to write parametric objects in
a direct algebraic style while keeping the evaluation environment narrow.

\section{Intended audience}

This manual is written for mathematics illustrators who want direct control
over how 3D figures are constructed and displayed in TikZ. It is especially
well suited to users who prefer to describe geometry algebraically: by giving
vectors, matrices, parametric expressions, and predicates, rather than by
delegating the whole rendering problem to a black-box graphics engine.

It is also written for readers who want the software to remain pedagogically
transparent. A great deal of graphics software can produce acceptable output
without showing the user why the output is correct. lua-tikz3dtools takes a
different position. It exposes enough of the underlying structure that the
user can reason about the geometry, the tessellation, the transformations,
the clipping predicates, and the occlusion itself.

\section{Scope of this manual}

This manual documents version~3.0.0 of the package.  It covers the command
interface exposed by the style file, the expression environment used by the
Lua backend, and the practical workflow for building occlusion-aware 3D
illustrations in TikZ.  Readers who want the algorithmic details should
consult the TUGboat article~\cite{nice2025luatikz3dtools}; the present
document concentrates on how to use the package rather than how it works
internally.

The package is centered on a simplicial pipeline.  Parametric curves are
sampled into line segments.  Parametric surfaces are sampled into triangles.
Parametric solids are currently represented through tessellated boundary
surfaces.  Directional lights contribute to a brightness value used during
triangle rendering.  Filters may be supplied as small Lua predicates which
are evaluated on the resulting simplices.

As in the article, the conceptual frame here is the painter's algorithm
rather than a z-buffer.  That choice is deliberate.  The package is designed
for document preparation, where the user benefits from explicit and
deterministic geometry.  The discussion that follows therefore concentrates on
how to define scenes clearly and how to make the package produce diagrams
whose occlusion is both correct and understandable.

\begin{figure}[tbp]
    \centering
    \begin{tikzpicture}
        \setobject[
            name = {view},
            object = {
                Matrix.zyzrotation3(pi/2, pi/2+0.1, 3.75*pi/6)
            }
        ]
        \appendlight[v={return Vector:new{1, 1, 1, 1}}]
        % Sphere
        \appendsurface[
            ustart = {0}, ustop = {tau}, usamples = {24},
            vstart = {0}, vstop = {pi}, vsamples = {16},
            v = {return Vector:new{
                1.5*sin(v)*cos(u),
                1.5*sin(v)*sin(u),
                1.5*cos(v),
                1
            }},
            transformation = {view},
            fill options = {
                preaction = {fill opacity=0.85, fill=ltdtbrightness},
                postaction = {draw, line width=0.15pt,
                    line join=round, line cap=round}
            }
        ]
        % Helix threading through the sphere
        \appendcurve[
            ustart = {-2.5*pi}, ustop = {2.5*pi}, usamples = {120},
            v = {return Vector:new{
                (1 + 0.3*u)*cos(3*u)*0.5,
                (1 + 0.3*u)*sin(3*u)*0.5,
                0.35*u,
                1
            }},
            transformation = {view},
            draw options = {red, thick, line cap=round}
        ]
        \displaysimplices
    \end{tikzpicture}
    \caption{A sphere with a helix threading through it.  The package
    handles occlusion between surfaces and curves: segments of the helix
    that pass behind the sphere are hidden, while those in front are drawn
    on top.  This mixed-type occlusion is one of the package's core
    capabilities.}
\end{figure}

\begin{figure}[tbp]
    \centering
    \begin{tikzpicture}
        \setobject[
            name = {view},
            object = {Matrix.xrotation3(-pi/5):multiply(Matrix.zrotation3(pi/6))}
        ]
        \appendlight[v={return Vector:new{1, 0.5, 1.5, 1}}]
        % First surface: a monkey saddle
        \appendsurface[
            ustart = {-1.2}, ustop = {1.2}, usamples = {24},
            vstart = {-1.2}, vstop = {1.2}, vsamples = {24},
            v = {return Vector:new{
                2*u,
                2*v,
                0.5*(u*u*u - 3*u*v*v),
                1
            }},
            transformation = {view},
            fill options = {
                preaction = {fill=cyan!30!ltdtbrightness},
                postaction = {draw=black, line width=0.15pt,
                    line join=round}
            }
        ]
        % Second surface: a tilted plane intersecting the saddle
        \appendsurface[
            ustart = {-1.2}, ustop = {1.2}, usamples = {8},
            vstart = {-1.2}, vstop = {1.2}, vsamples = {8},
            v = {return Vector:new{2*u, 2*v, 0.4*v + 0.2, 1}},
            transformation = {view},
            fill options = {
                preaction = {fill=orange!25!ltdtbrightness, fill opacity=0.7},
                postaction = {draw=orange!50!black, line width=0.2pt,
                    line join=round}
            }
        ]
        \displaysimplices
    \end{tikzpicture}
    \caption{A monkey saddle $z = \tfrac{1}{2}(x^3 - 3xy^2)$ intersected
    by a tilted plane.  The package partitions the simplices of both
    surfaces where they cross and draws each fragment in the correct
    depth order.  Without partitioning, one surface would simply paint
    over the other at the intersection.}
\end{figure}

\begin{figure}[tbp]
    \centering
    \begin{tikzpicture}
        \appendtriangle[
             A = {Vector:new{-2,0,0,1}},
            B = {Vector:new{2,0,0,1}},
            C = {Vector:new{2,0.5,0,1}},
            fill options = {fill=red!25, draw=red!60!black, thin}
        ]
        \appendtriangle[
            A = {Vector:new{0.5,-0.5,-0.2,1}},
            B = {Vector:new{1,-0.5,-0.2,1}},
            C = {Vector:new{1,5,0.8,1}},
            fill options = {fill=green!25, draw=green!50!black, thin}
        ]
        \appendtriangle[
            A = {Vector:new{2,4,-0.3,1}},
            B = {Vector:new{2,3.5,-0.3,1}},
            C = {Vector:new{-1.5,-0.5,0.6,1}},
            fill options = {fill=blue!25, draw=blue!60!black, thin}
        ]
        \displaysimplices
    \end{tikzpicture}
    \caption{Three cyclically occluding triangles.}
\end{figure}