%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % 3D extensions for MetaPost by Anthony Phan. % file: m3Dmanual.tex % last modification: january 11, 2006 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \input m3Dmanmac \input epsf \useoptions{preprint,magstep1,english,AMSsectioning} \def\TM{\textsuperscript{TM}} \def\cs#1{\ifmmode\hbox{\tt#1}\else{\tt#1}\fi}% \def\var#1{\ifmmode\hbox{\it#1\/}\else{\it#1\/}\fi}% \newdimen\fboxsep\fboxsep=2pt \newdimen\fboxrule\fboxrule=0.4pt \def\mybox#1{\vcenter{\setbox0=\hbox{\vrule width\fboxrule \vbox{\hrule height\fboxrule\kern\fboxsep \hbox{\kern\fboxsep\epsfbox{#1}\kern\fboxsep}\kern\fboxsep \hrule height\fboxrule}\vrule width\fboxrule} \copy0\kern\fboxsep\hbox to\wd0{\hss\tt#1\hss}}}% %\def\mybox#1{\hbox{\tt#1}} \title{m3D package manual} \author{Anthony Phan, \date} \maketitle \section*{Introduction} In the second half of the nineties (of the past century), I discovered \TeX, MetaFont and, then, MetaPost. I was truly enthousiastic about this last tool since it allows a very simple inclusion of images produced by some MetaFont-like language into \TeX\ documents. My first attempt in 3D pictures with MetaPost was very simple: the projection system was absolutely rigid and the picture was composed of a few lines and labels and only 4 filled flat surfaces whose colors where static. Then I understood that it is necessary to have a parametrizable frame since one does not always know if a picture, viewed from a certain angle, will be meaningfull or not. So the first and main step was done: having a parametrizable frame, dealing with space coordinates, drawing contours if their projection on the screen is well-oriented. Then I heard of Denis Roegel's package ``3D''. Its syntax didn't fit what I could have in mind about 3D-programming in MetaPost, but it features facilities for {\tt eps} to {\tt gif} conversion and animation. I stolled these animation facilities in order to have fun and also to find the best angle for my picture. Then I began to make more complex designs intended to illustrate my web pages\dots What was my {\it leitmotiv}\/ was to keep the closest as possible to usual MetaFont/MetaPost programming, but also to consider every 3-dimensional object as enough complex to deserve a quite technical code. So I've come to think that what could be nice should be to have a stable and powerfull basic program and add to it libraries of common objects. Some more complex objects could then be build up from those more basic ones by moving them, rotating them and rescaling them. My idea about objects is certainly not related to object-programming, it is just the naive notion of solid bodies. The aim one can have with such a project is boundless. The package ``m3D'' remains still in progress. I'm only glad to be able to use it when a friend ask me if I can draw a better picture than he does. Also one of my believes is that any MetaPost programmer prefers to build his/her own macros' system than relying on someone else's programs---especially when these ones are claimed to be unstable. Such a programmer would simply have an overview of the syntax, of some special hacks, may publish his/her own programs on Internet and in this way give some feed back to every other people interested in such programming. \section{Basic concepts} As anyone knows, MetaPost provides standard facilities for manipulating 3~dimensional vectors with the variable type ``color'': type-check, addition, substraction, scalar multiplication. What may be seen as missing is affine transformations of 3~dimensional vectors or pictures but no one would complain about that since MetaPost is a 2-dimensional oriented programming language and anyone would accept using some higher level control sequences for such tasks. \section{Coordinates system} \section{Projection system} \section{Rendering parameters} \list{definitions} \item{\tt ObsZ :=} internal numeric. \item{\tt Resolution :=} internal numeric. \item{\tt Phong :=} internal numeric. \item{\tt Specularity :=} internal numeric. \item{\tt Luminosity :=} internal numeric. \item{\tt Contrast :=} internal numeric. \item{\tt Fog :=} internal numeric. \item{\tt FogZ :=} internal numeric. \item{\tt FogHalf :=} internal numeric. \item{\tt fineplot :=} boolean. \item{\tt LightAtInfinity :=} boolean. \item{\tt LightSource :=} color. \item{\tt ObjectColor :=} color. \endlist \section{About the light source} There is only one light source defined in {\tt m3Dplain.mp}. It can be located at infinity ({\tt LightAtInfinity := true}) or at some point in the scenery ({\tt LightAtInfinity := false}). In both cases its coordinates {\tt LightSource} refer to the global screen frame and are not modified when objects are translated or rotated, that is that the light is fixed for the observer. If one wants to link the light source to a peculiar object, one has to write within the definition of the object something like $$ \hbox{\tt LightSource := GDir(x,y,z)} $$ if the light source is located at infinity, or $$ \hbox{\tt LightSource := GCoord(x,y,z)} $$ if the light source is located at some point in space ({\tt (x,y,z)} are here {\it local}\/ coordinates). One should notice that it is barely the only direct use of the control sequences {\tt GDir} and {\tt GCoord}. If one needs more than one light source, one has to define anew the control sequence {\tt Light} of {\tt m3Dplain.mp} (good luck since it is already a heavy machinery). \section{Ordering and hidden bodies} Drawing a single convex body is an easy task: one just have to draw every facet which contour is seen, or projected, as a positively (resp. negatively) oriented path when drawing its exterior (resp. interior) side. So, hidden facets are no problem in these cases. Switching between inside and outside can be done with \cs{Inside} and \cs{Outside} control sequences. They simply reverse the condition about orientation. When dealing with non-convex bodies, one has to decompose these bodies into their convex parts and draw them in a proper order. Thus, we come to ordering. A fairly tricky control sequence named \cs{QuickSort} has been designed for this purpose. Its argument is some text that must contain at least two terms and its output is a control sequence named \cs{SortedList} which content is the previous (expanded) list ordered with respect to a \cs{SortCriterion}. \cs{SortCriterion} is a control sequence with two arguments (members of the list which is to be sorted) whose replacement text is a boolean. By default, these arguments are triples and the condition is about their actual depth relatively to the current observer. Thus \cs{QuickSort(\var{list of triples})} would output \cs{SortedList} whose replacement text is just the expected ordered list of triples. One can change this just by adapting \cs{SortCriterion} in order to sort numerics, pairs, strings, \dots It wouldn't be very elegant to sort things this way if one wants to perform a list of actions with respect to the depth of a list of points in space. A more natural way to do so is to use the following procedure: \cs{OnDepth;} \cs{Refpoint \var{triple};} \cs{Action (\var{delimited control sequences});} ... \cs{endOnDepth;} \noindent What this procedure does is the following: save and reset a few things at the \cs{OnDepth} statement; increase the \cs{Action\_counter} and stores the current reference point (a \var{triple}) at \cs{Refpoint} invocation; stores the \var{delimited control sequences} into a variable control sequence numbered (here there is a little trick that I have been looking for a very very long time) with the current \cs{Action\_counter}; at \cs{endOnDepth} orders the list $1,\dots,\cs{Action\_counter}$ with respect to the depth of the reference points and then performs actions with respect to the sorted list. The most interesting thing with this procedure is that actions may depend on some parameters just as loop or macro parameters. Note that the \cs{SortCriterion} has a special and temporary meaning when performing \cs{endOnDepth}: its two arguments are then some indexes in $1,\dots,\cs{Action\_counter}$ and the comparison is done between the depths of the two corresponding reference points. \section{Integrating text} This is clear that for some nice and funny pictures, one has to integrate text in the three dimensional space, for instance when moving a text around a picture as I've done once or twice. This is rather particular. Defining any general scheme for doing so seems to me rather pointless: it is too complicated, it is hard to imagine what people would like to do, etc. Anyway, some control sequence that allows to move flat text around would be a basic stuff. Also, basic programming of such things may help to design special control sequences for more complicated tasks. \subsection{Simple text} An object named \cs{simpletext} is defined in \cs{m3Dplain.mp}. Its specific parameters consist, first, in a string describing the alignment (\cs{"left"}, \cs{"justify"}, \cs{"center"} or \cs{"right"}) and a string telling where on the text the reference point should be (typically \cs{"right"}, \cs{"urt"}, \cs{"top"}, \cs{"ulft"}, \cs{"left"}, \cs{"llft"}, \cs{"bot"}, \cs{"lrt"} or [say!] \cs{"center"}), then, in a list of strings which would be displayed one above another. For instance, at a top level ({\it see}\/ further on about the scale parameter), \tabindent=\parindent \verbatim UseObject(simpletext, Origin, (90, 0, 90), 10pt, "justify", "ulft", "Come let me sing into your ear;", "Those dancing days are gone,", "All that silk and satin gear;", "Crouch upon a stone,", "Wrapping that foul body up", "In as foul a rag:", "I carry the sun in a golden cup;", "The moon in a silver bag.")); \endverbatim \noindent would display, at basepoint {\tt Origin}, with frame the current one rotated by $(90,0,90)$, with scale $10\,\rm pt$, the first part of J.B.~Yeats' poem \og Those dancing days are gone\fg. If it is reasonable, each line would be justified and the basepoint would correspond to the upper left corner of the text. The {\tt simpletext} object uses a font named by the string {\tt mthreeDfont} (default value: {\tt"rphvb"}). Its design size is defined by the numerical variable named {\tt mtheeDfontsize} (default value: {\tt10pt}). The numerical parameter \cs{baselineskip} parameter has its usual role (default value: {\tt12pt}). These parameters are only related to the font, not to the {\tt CurrentScale}. Thus, when using {\tt simpletext} into an object, beware of the \var{scale} given in statements like $$ \displaylines{\indent \cs{UseObject(simpletext, \var{origin}, \var{Euler angles}, \var{scale},} \hfill\cr\hfill \cs{\var{alignment string}, \var{location string}, \var{list of strings})}\indent} $$ since \var{scale} must be a {\it local scale}. Justification is obtained by stretching the normal space width of the font up to a \cs{TextStretchFactor} (whose default value is $2$ which is quite large). Many successive spaces into a sentence count as as many spaces: {\it they are not reduced into a single space.} Each character is drawn separately just to make sure that the affine transformation acting on the character would be approximatively correct if the projection is not linear. {\it Since every character would have a special scaling, one must set\/ \cs{prologues}\/ to 1 or 2 in order to not overflow MetaPost capacities (the whole font will simply be declared at the beginning of the eps figure and not every character with its own transformation).} Of course, one should use PostScript\TM\ fonts for such use. This is why we have introduced {\tt mthreeDfont}. \subsection{Curved text} Planned but not released. \remark Remember that annotating graphics can still be done with usual control sequence like $$ \cs{label{\it.loc}({\it label}, proj($x$, $y$, $z$))} $$ since things like {\tt simpletext} or {\tt curvedtext} are rather for very special effects. \endremark \section{Animations} \subsection{Introduction} Denis Roegel demonstrated that it is possible to use usual Unix tools to merge a list of MetaPost outputs into an animated GIF image (3D package). I've learned a lot from his ``metapost to shell'' script. The idea is the following: first, keep track of the maximum boundary limits of every eps outputs; then convert these eps outputs into PostScript\TM\ or eps files with these maximum boundary limits; convert these last files to, say, simple GIF images; then merge all these images into an animation. \subsection{How-to with m3D} With {\tt m3Dplain} (as for {\tt 3D}), (hidden) numerics named \cs{xmin\_}, \cs{xmax\_}, \cs{ymin\_} and \cs{ymax\_} are updated at every figure ends through a control sequence named {\tt compute\_bbox} (embedded by {\tt m3Dplain.mp} into \cs{extra\_endfig}). Executing $$ \hbox{\tt Animate({\it numeric}, {\it boolean or color})} $$ at the end of the file would produce an external file whose name is, by default, {\tt animate-script}. Once the MetaPost job finished, under Unix-like system, execute $$ \hbox{\tt bash animate-script} $$ from a console ({\tt xterm} or such) in the right directory. The final output is \cs{jobname.gif} where {\tt jobname} is the actual name of the MetaPost program. \subsection{External programs} This script requires the following programs: {\tt sed} and {\tt convert}. We choose to use {\tt sed} to change the boundary parameters of every MetaPost output---the resulting temporary files are named {\tt jobname.xxx.eps} where {\tt jobname.xxx} is the name of one of the MetaPost outputs. The PostScript\TM\ to GIF conversion was performed with the Netpbm library in Roegel's macros and their merging into an animation was performed by {\tt gifmerge} (a non standard but very nice Unix program freely available on the web). These last years, ImageMagick (copyrighted first by Dupont de Nemours, then by ImageMagick Studio, but quite free in fact) has spread over almost every Linux distribution. It is a very high quality tool that converts anything into everything, even animations. One of the basic control sequence is {\tt convert} which is the one called by the former script. \subsection{Details} The following provides more detailed explanations. \list{definitions} \item{\tt Animate({\it numeric}, {\it boolean or color})} Control sequence whose first parameter is the border in {\tt bp} provided with no units, and the second one is a color or a boolean. When the second parameter is a color, this color will be made transparent in the animation. When it is a boolean, {\tt background} (color) will be made transparent if the boolean is true, and no transparency will be made if this boolean is false. \item{\tt AnimateScript} String variable, name of the (bash) script file which is output by {\tt Animate}. \item{\tt AnimateQuality} Numerical variable, typical values are 1, 2, 4\dots \item{\tt AnimateDelay} Numerical variable, time in $1/100$ seconds between every image in the animation. \item{\tt AnimateLoop} Numerical variable, parameter for the animation, its dafult value is equal to 0 (infinite loop). \item{\tt compute\_bbox} and also \cs{xmin\_}, \cs{xmax\_}, \cs{ymin\_}, \cs{ymax\_} have been explained before. \endlist \section{Outputting encapsuled PostScript directly} \cs{DirectEPS \var{filename};} ... \cs{endDirectEPS;} \section{Some samples} The first picture is made with \cs{Fill} equal to \cs{TechnoFill} (I have to change this name one day), the next one with \cs{Fill} equal to \cs{WireFill} (more conventional). I have also added a text (W.B. Yeats) for testing the \cs{simpletext} object. There is, in the second picture, a cylinder but the most important is the use of an object named \cs{rope}: given a path in space through $x(t)$, $y(t)$, $z(t)$, a radius $r$, a range for $t$, this object is what one can expect it to be. Also computations are quite fragile (second order) and may leads to unexpected and ugly effects. If the object \cs{cylinder} is defined in \cs{m3Dlib01.mp}, \cs{rope} is defined in \cs{m3Dplain.mp} since I think it may be a basic tool. $$\mybox{m3Dmanual.1}$$ $$\mybox{m3Dmanual.2}$$ Here there are two Sierpinski--Menger objects: the sponge (object named \cs{sierpinskip\_sponge}) and the gasket (object named \cs{sierpinskip\_gasket}). The sponge is drawn with \cs{Fill} equal to \cs{SolidFill} and the gasket with \cs{Fill} equal to \cs{SolidWireFill}. Both objects are defined in \cs{m3Dlib01.mp}. The gasket---since it grows as $4^n$ where $n$ is the level of recursion---is a lot easier to draw than the sponge---which grows as $20^n$. Reaching the level 3 on my current MetaPost implementation for the sponge was not an easy task. $$\mybox{m3Dmanual.3}\qquad\mybox{m3Dmanual.4}$$ $$\mybox{m3Dmanual.5}\qquad\mybox{m3Dmanual.6}$$ $$ \mybox{m3Dmanual.7} $$ This last example shows the use of the object named \cs{cylinderlike} which is defined in \cs{m3Dplain.mp}. $$ \mybox{m3Dmanual.8} $$ Its specific parameters are an $xOy$-cycle path and the height of the cyclinder. Thus, former picture as be obtained with \verbatim beginfig(8); UseObject(cylinderlike,(0,0,0),(0,0,0),1cm, for i = 0 upto 4: 2dir(i/5*360)--dir((i+0.5)/5*360)-- endfor cycle, 1); endfig; \endverbatim \noindent which is rather simple. %\verbatimfile{m3Dplain.mp} \bye